blob: ecb4bbf1618346b5055f47a0ab867f7d8d6eaf11 [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright 2019 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A utility for generating a file list.
Each entry in the FileList contains the file path and a path relative to the
root directory that can be used for creating archives.
"""
import logging
import os
import _env # pylint: disable=relative-import,unused-import
from starboard.build import port_symlink
class FileList(object):
"""Makes it easy to include files for things like archive operations."""
def __init__(self):
self.file_list = [] # List of 2-tuples: file_path, archive_path
self.symlink_dir_list = [] # Same
def AddAllFilesInPath(self, root_dir, sub_path):
"""Starting at the root path, the sub_paths are searched for files."""
all_files = []
all_symlinks = []
if os.path.isfile(sub_path):
self.AddFile(root_dir, sub_path)
elif not os.path.isdir(sub_path):
raise IOError('Expected root directory to exist: %s' % sub_path)
for root, dirs, files in port_symlink.OsWalk(sub_path):
for f in files:
full_path = os.path.abspath(os.path.join(root, f))
all_files.append(full_path)
for dir_name in dirs:
full_path = os.path.abspath(os.path.join(root, dir_name))
if port_symlink.IsSymLink(full_path):
all_symlinks.append(full_path)
for f in all_files + all_symlinks:
self.AddFile(root_dir, f)
def AddAllFilesInPaths(self, root_dir, sub_paths):
if not os.path.isdir(root_dir):
raise IOError('Expected root directory to exist: ' + str(root_dir))
for p in sub_paths:
self.AddAllFilesInPath(root_dir=root_dir, sub_path=p)
def AddFile(self, root_path, file_path):
if port_symlink.IsSymLink(file_path):
self.AddSymLink(root_path, file_path)
else:
archive_name = _OsGetRelpath(file_path, root_path)
self.file_list.append([file_path, archive_name])
def AddSymLink(self, relative_dir, link_file):
rel_link_path = _OsGetRelpath(link_file, relative_dir)
target_path = _ResolveSymLink(link_file)
assert os.path.exists(target_path)
rel_target_path = _OsGetRelpath(target_path, relative_dir)
self.symlink_dir_list.append([relative_dir, rel_link_path, rel_target_path])
def Print(self):
for f in self.file_list:
print 'File: %s' % f
for s in self.symlink_dir_list:
print 'Symlink: %s' % s
def _ResolveSymLink(link_file):
target_path = port_symlink.ReadSymLink(link_file)
if os.path.exists(target_path): # Absolute path
return target_path
else:
return os.path.join(link_file, target_path) # Relative path from link_file.
def _FallbackOsGetRelPath(path, start_dir):
path = os.path.normpath(path)
start_dir = os.path.normpath(start_dir)
common_prefix = os.path.commonprefix([path, start_dir])
split_list = common_prefix.split(os.sep)
path_parts = path.split(os.sep)
for _ in range(len(split_list)):
path_parts = path_parts[1:]
return os.path.normpath(os.path.join(*path_parts))
def _OsGetRelpath(path, start_dir):
try:
return os.path.relpath(path, start_dir)
except ValueError:
try:
# Windows: nt paths checks the drive specifier, which is given by the
# abspath operation.
return os.path.relpath(os.path.abspath(path), os.path.abspath(start_dir))
except ValueError:
try:
# Last resort: do a string comparison to get relative path.
rel_path = _FallbackOsGetRelPath(path, start_dir)
if not os.path.exists(os.path.join(start_dir, rel_path)):
raise ValueError('% does not exist.' % os.path.abspath(rel_path))
return rel_path
except ValueError as err:
logging.exception('Error %s while calling os.path.relpath(%s, %s)',
err, path, start_dir)
TYPE_NONE = 'NONE'
TYPE_SYMLINK_DIR = 'SYMLINK DIR'
TYPE_DIRECTORY = 'DIR'
TYPE_FILE = 'FILE'
def GetFileType(f):
if not os.path.exists(f):
return TYPE_NONE
elif port_symlink.IsSymLink(f):
return TYPE_SYMLINK_DIR
elif os.path.isdir(f):
return TYPE_DIRECTORY
else:
assert os.path.isfile(f)
return TYPE_FILE