blob: 33c417b3879f6e221e5a1e3bc80b06cee46c1776 [file] [log] [blame] [edit]
#!/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 portable interface for symlinking."""
import argparse
import logging
import os
import shutil
import sys
import _env # pylint: disable=relative-import,unused-import
from starboard.tools import util
################################################################################
# API #
################################################################################
def IsWindows():
return _IsWindows()
# Platform neutral version os os.path.islink()
def IsSymLink(path):
return _IsSymLink(path=path)
def MakeSymLink(from_folder, link_folder):
"""Makes a symlink.
Args:
from_folder: Path to the actual folder
link_folder: Path to the link
Returns:
None
"""
_MakeSymLink(from_folder=from_folder, link_folder=link_folder)
def ReadSymLink(link_path):
return _ReadSymLink(link_path=link_path)
def DelSymLink(link_path):
return _DelSymLink(link_path=link_path)
def Rmtree(path):
return _Rmtree(path=path)
def OsWalk(root_dir, topdown=True, onerror=None, followlinks=False):
return _OsWalk(root_dir=root_dir,
topdown=topdown,
onerror=onerror,
followlinks=followlinks)
################################################################################
# IMPL #
################################################################################
def _IsWindows():
return sys.platform in ['win32', 'cygwin']
def _IsSymLink(path):
if _IsWindows():
# pylint: disable=g-import-not-at-top
from starboard.build import win_symlink
return win_symlink.IsReparsePoint(path)
else:
return os.path.islink(path)
def _MakeSymLink(from_folder, link_folder):
if _IsWindows():
# pylint: disable=g-import-not-at-top
from starboard.build import win_symlink
win_symlink.CreateReparsePoint(from_folder, link_folder)
else:
util.MakeDirs(os.path.dirname(link_folder))
os.symlink(from_folder, link_folder)
def _ReadSymLink(link_path):
"""Returns a absolute path to the folder referred to by the link_path."""
if IsWindows():
# pylint: disable=g-import-not-at-top
from starboard.build import win_symlink
path = win_symlink.ReadReparsePoint(link_path)
else:
try:
path = os.readlink(link_path)
except OSError:
path = None
return path
def _DelSymLink(link_path):
if IsWindows():
# pylint: disable=g-import-not-at-top
from starboard.build import win_symlink
win_symlink.UnlinkReparsePoint(link_path)
else:
os.unlink(link_path)
def _Rmtree(path):
"""See Rmtree() for documentation of this function."""
if not os.path.exists(path):
return
if _IsWindows():
# pylint: disable=g-import-not-at-top
from starboard.build import win_symlink
win_symlink.RmtreeShallow(path)
else:
if os.path.islink(path):
os.unlink(path)
else:
shutil.rmtree(path)
def _OsWalk(root_dir, topdown=True, onerror=None, followlinks=False):
if IsWindows():
# pylint: disable=g-import-not-at-top
from starboard.build import win_symlink
return win_symlink.OsWalk(root_dir, topdown, onerror, followlinks)
else:
return os.walk(root_dir, topdown, onerror, followlinks)
def _CreateArgumentParser():
"""Creates an argument parser for port_symlink."""
class MyParser(argparse.ArgumentParser):
def error(self, message):
sys.stderr.write('error: %s\n' % message)
self.print_help()
sys.exit(2)
help_msg = (
'Example 1:\n'
' python port_link.py --link "actual_folder_path" "link_path"\n\n'
'Example 2:\n'
' python port_link.py --link "../actual_folder_path" "link_path"\n\n')
# Enables new lines in the description and epilog.
formatter_class = argparse.RawDescriptionHelpFormatter
parser = MyParser(epilog=help_msg, formatter_class=formatter_class)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--link',
help='Issues an scp command to upload src to remote_dst',
metavar='"path"',
nargs=2)
return parser
def main():
util.SetupDefaultLoggingConfig()
parser = _CreateArgumentParser()
args = parser.parse_args()
folder_path, link_path = args.link
if '.' in folder_path:
d1 = os.path.abspath(folder_path)
else:
d1 = os.path.abspath(os.path.join(link_path, folder_path))
if not os.path.isdir(d1):
logging.warning('%s is not a directory.', d1)
MakeSymLink(from_folder=folder_path, link_folder=link_path)
if __name__ == '__main__':
main()