[Lldb-commits] [lldb] r247903 - Add sync-source.py utility.
Todd Fiala via lldb-commits
lldb-commits at lists.llvm.org
Thu Sep 17 10:14:32 PDT 2015
Author: tfiala
Date: Thu Sep 17 12:14:31 2015
New Revision: 247903
URL: http://llvm.org/viewvc/llvm-project?rev=247903&view=rev
Log:
Add sync-source.py utility.
See:
http://reviews.llvm.org/D12940
for more details.
See utils/sync-source/README.txt for documentation
and a sample .sync-sourcerc file.
Added:
lldb/trunk/utils/sync-source/
lldb/trunk/utils/sync-source/README.txt
lldb/trunk/utils/sync-source/lib/
lldb/trunk/utils/sync-source/lib/transfer/
lldb/trunk/utils/sync-source/lib/transfer/protocol.py
lldb/trunk/utils/sync-source/lib/transfer/rsync.py
lldb/trunk/utils/sync-source/lib/transfer/transfer_spec.py
lldb/trunk/utils/sync-source/pylintrc
lldb/trunk/utils/sync-source/sync-source.py
Added: lldb/trunk/utils/sync-source/README.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/utils/sync-source/README.txt?rev=247903&view=auto
==============================================================================
--- lldb/trunk/utils/sync-source/README.txt (added)
+++ lldb/trunk/utils/sync-source/README.txt Thu Sep 17 12:14:31 2015
@@ -0,0 +1,293 @@
+sync-source.py
+
+OVERVIEW
+
+The sync-source.py utility transfers groups of files between
+computers. The primary use case is to enable developing LLVM project
+software on one machine, transfer it efficiently to other machines ---
+possibly of other architectures --- and test it there. sync-source.py
+supports configurable, named source-to-destination mappings and has a
+transfer agent plug-in architecture. The current distribution provides
+an rsync-over-ssh transfer agent.
+
+The primary benefits of using sync-source.py are:
+
+* Provides a simple, reliable way to get a mirror copy of primary-
+ machine files onto several different destinations without concern
+ of compromising the patch during testing on different machines.
+
+* Handles directory-mapping differences between two machines. For
+ LLDB, this is helpful when going between OS X and any other non-OS X
+ target system.
+
+EXAMPLE WORKFLOW
+
+This utility was developed in the context of working on the LLDB
+project. Below we show the transfers we'd like to have happen,
+and the configuration that supports it.
+
+Workflow Example:
+
+* Develop on OS X (primary machine)
+* Test candidate changes on OS X.
+* Test candidate changes on a Linux machine (machine-name: lldb-linux).
+* Test candidate changes on a FreeBSD machine (machine-name: lldb-freebsd).
+* Do check-ins from OS X machine.
+
+Requirements:
+
+* OS X machine requires the lldb source layout: lldb, lldb/llvm,
+ lldb/llvm/tools/clang. Note this is different than the canonical
+ llvm, llvm/tools/clang, llvm/tools/lldb layout that we'll want on
+ the Linux and FreeBSD test machines.
+
+* Linux machine requires the llvm, llvm/tools/clang and
+ llvm/tools/lldb layout.
+
+* FreeBSD machine requires the same layout as the llvm machine.
+
+sync-source.py configuration in ~/.sync-sourcerc:
+
+# This is my configuration with a comment. Configuration
+# files are JSON-based.
+{ "configurations": [
+ # Here we have a collection of named configuration blocks.
+ # Configuration blocks can chain back to a parent by name.
+ {
+ # Every block has a name so it can be referenced from
+ # the command line or chained back to by a child block
+ # for sharing.
+ "name": "base_tot_settings",
+
+ # This directive lists the "directory ids" that we'll care
+ # about. If your local repository has additional directories
+ # for other projects that need to ride along, add them here.
+ # For defaulting purposes, it makes sense to name the
+ # directory IDs as the most likely name for the directory
+ # itself. For stock LLDB from top of tree, we generally only
+ # care about lldb, llvm and clang.
+ "dir_names": [ "llvm", "clang", "lldb" ],
+
+ # This section describes where the source files live on
+ # the primary machine. There should always be a base_dir
+ # entry, which indicates where in the local filesystem the
+ # projects are rooted. For each dir in dir_names, there
+ # should be either:
+ # 1. an entry named {dir-id}_dir (e.g. llvm_dir), which
+ # specifies the source directory for the given dir id
+ # relative to the base_dir entry, OR
+ # 2. no entry, in which case the directory is assumed to
+ # be the same as {dir-id}. In the example below, the
+ # base_dir-relative directory for the "lldb" dir-id is
+ # defaulted to being "lldb". That's exactly what
+ # we need in an OS X-style lldb dir layout.
+ "source": {
+ "base_dir": "~/work/lldb-tot",
+ "llvm_dir": "lldb/llvm",
+ "clang_dir": "lldb/llvm/tools/clang"
+ },
+
+ # source_excludes covers any exclusions that:
+ # * should be applied when copying files from the source
+ # * should be excluded from deletion on the destination
+ #
+ # By default, ".git", ".svn" and ".pyc" are added to
+ # all dir-id exclusions. The default excludes can be
+ # controlled by the sync-source.py --default-excludes
+ # option.
+ #
+ # Below, I have transfer of the lldb dir skip everything
+ # rooted at "/llvm" below the the lldb dir. This is
+ # because we want the source OS X lldb to move to
+ # a destination of {some-dest-root}/llvm/tools/lldb, and
+ # not have the OS-X-inverted llvm copy over with the lldb
+ # transfer portion. We'll see the complete picture of
+ # how this works when we get to specifying destinations
+ # later on in the config.
+ #
+ # We also exclude the "/build" and "/llvm-build" dir rooted in
+ # the OS X-side sources. The Xcode configuration on this
+ # OS X machine will dump lldb builds in the /build directory
+ # relative to the lldb dir, and it will build llvm+clang in
+ # the /llvm-build dir relative to the lldb dir.
+ #
+ # Note the first forward slash in "/build" indicates to the
+ # transfer agent that we only want to exclude the
+ # ~/work/lldb-tot/lldb/build dir, not just any file or
+ # directory named "build" somewhere underneath the lldb
+ # directory. Without the leading forward slash, any file
+ # or directory called build anywhere underneath the lldb dir
+ # will be excluded, which is definitely not what we want here.
+ #
+ # For the llvm dir, we do a source-side exclude for
+ # "/tools/clang". We manage the clang transfer as a separate
+ # entity, so we don't want the movement of llvm to also move
+ # clang.
+ #
+ # The llvm_dir exclusion of "/tools/lldb" is the first example
+ # of an exclude targeting a requirement of the destination
+ # side. Normally the transfer agent will delete anything on
+ # the destination that is not present on the source. It is
+ # trying to mirror, and ensure both sides have the same
+ # content. The source side of llvm on OS X does not have a
+ # "/tools/lldb", so at first this exclude looks non-sensical.
+ # But on the canonical destination layout, lldb lives in
+ # {some-dest-root}/llvm/tools/lldb. Without this exclude,
+ # the transfer agent would blow away the tools/lldb directory
+ # on the destination every time we transfer, and then have to
+ # copy the lldb dir all over again. For rsync+ssh, that
+ # totally would defeat the huge transfer efficiencies gained
+ # by using rsync in the first place.
+ #
+ # Note the overloading of both source and dest style excludes
+ # ultimately comes from the rsync-style exclude mechanism.
+ # If it wasn't for that, I would have separated source and
+ # dest excludes out better.
+ "source_excludes": {
+ "lldb_dir": ["/llvm", "/build", "/llvm-build"],
+ "llvm_dir": ["/tools/lldb", "/tools/clang"]
+ }
+ },
+
+ # Top of tree public, common settings for all destinations.
+ {
+ # The name for this config block.
+ "name": "common_tot",
+
+ # Here is our first chaining back to a parent config block.
+ # Any settings in "common_tot" not specified here are going
+ # to be retrieved from the parent.
+ "parent": "base_tot_settings",
+
+ # The transfer agent class to use. Right now, the only one
+ # available is this one here that uses rsync over ssh.
+ # If some other mechanism is needed to reach this destination,
+ # it can be specified here in full [[package.]module.]class form.
+ "transfer_class": "transfer.rsync.RsyncOverSsh",
+
+ # Specifies the destination-root-relative directories.
+ # Here our desination is rooted at:
+ # {some-yet-to-be-specified-destination-root} + "base_dir".
+ # In other words, each destination will have some kind of root
+ # for all relative file placement. We'll see those defined
+ # later, as they can change per destination machine.
+ # The block below describes the settings relative to that
+ # destination root.
+ #
+ # As before, each dir-id used in this configuration is
+ # expected to have either:
+ # 1. an entry named {dir-id}_dir (e.g. llvm_dir), which
+ # specifies the destination directory for the given dir id
+ # relative to the dest_root+base_dir entries, OR
+ # 2. no entry, in which case the directory is assumed to
+ # be the same as {dir-id}. In the example below, the
+ # dest_root+base_dir-relative directory for the "llvm" dir-id is
+ # defaulted to being "llvm". That's exactly what
+ # we need in a canonical llvm/clang/lldb setup on
+ # Linux/FreeBSD.
+ #
+ # Note we see the untangling of the OS X lldb-centric
+ # directory structure to the canonical llvm,
+ # llvm/tools/clang, llvm/tools/lldb structure below.
+ # We are mapping lldb into a subdirectory of the llvm
+ # directory.
+ #
+ # The transfer logic figures out which directories to copy
+ # first by finding the shortest destination absolute path
+ # and doing them in that order. For our case, this ensures
+ # llvm is copied over before lldb or clang.
+ "dest": {
+ "base_dir": "work/mirror/git",
+ "lldb_dir": "llvm/tools/lldb",
+ "clang_dir": "llvm/tools/clang"
+ }
+ },
+
+ # Describe the lldb-linux destination. With this,
+ # we're done with the mapping for transfer setup
+ # for the lldb-linux box. This configuration can
+ # be used either by:
+ # 1. having a parent "default" blockthat points to this one,
+ # which then gets used by default, or
+ # 2. using the --configuration/-c CONFIG option to
+ # specify using this name on the sync-source.py command line.
+ {
+ "name": "lldb-linux"
+ "parent": "common_tot",
+
+ # The ssh block is understood by the rsync+ssh transfer
+ # agent. Other agents would probably require different
+ # agent-specific details that they could read from
+ # other blocks.
+ "ssh": {
+ # This specifies the host name (or IP address) as would
+ # be used as the target for an ssh command.
+ "dest_host": "lldb-linux.example.com",
+
+ # root_dir specifies the global root directory for
+ # this destination. All destinations on this target
+ # will be in a directory that is built from
+ # root_dir + base_dir + {dir_id}_dir.
+ "root_dir" : "/home/tfiala",
+
+ # The ssh user is specified here.
+ "user": "tfiala",
+
+ # The ssh port is specified here.
+ "port": 22
+ }
+ },
+
+ # Describe the lldb-freebsd destination.
+ # Very similar to the lldb-linux one.
+ {
+ "name": "lldb-freebsd"
+ "parent": "common_tot",
+ "ssh": {
+ "dest_host": "lldb-freebsd.example.com",
+ # Specify a different destination-specific root dir here.
+ "root_dir" : "/mnt/ssd02/fialato",
+ "user": "fialato",
+ # The ssh port is specified here.
+ "port": 2022
+ }
+ },
+
+ # If a block named "default" exists, and if no configuration
+ # is specified on the command line, then the default block
+ # will be used. Use this block to point to the most common
+ # transfer destination you would use.
+ {
+ "name": "default",
+ "parent": "lldb-linux"
+ }
+]
+}
+
+Using it
+
+Now that we have a .sync-sourcerc file set up, we can do a transfer.
+The .sync-sourcerc file will be searched for as follows, using the
+first one that is found:
+
+* First check the --rc-file RCFILE option. If this is specified
+ and doesn't exist, it will raise an error and quit.
+
+* Check if the current directory has a .sync-sourcerc file. If so,
+ use that.
+
+* Use the .sync-sourcerc file from the user's home directory.
+
+Run the command:
+python /path/to/sync-source.rc -c {configuration-name}
+
+The -c {configuration-name} can be left off, in which case a
+configuration with the name 'default' will be used.
+
+After that, the transfer will occur. With the rsync-over-ssh
+transfer agent, one rsync per dir-id will be used. rsync output
+is redirected to the console.
+
+FEEDBACK
+
+Feel free to pass feedback along to Todd Fiala (todd.fiala at gmail.com).
Added: lldb/trunk/utils/sync-source/lib/transfer/protocol.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/utils/sync-source/lib/transfer/protocol.py?rev=247903&view=auto
==============================================================================
--- lldb/trunk/utils/sync-source/lib/transfer/protocol.py (added)
+++ lldb/trunk/utils/sync-source/lib/transfer/protocol.py Thu Sep 17 12:14:31 2015
@@ -0,0 +1,7 @@
+class Protocol(object):
+ def __init__(self, options, config):
+ self.options = options
+ self.config = config
+
+ def transfer(transfer_specs, dry_run):
+ raise "transfer must be overridden by transfer implementation"
Added: lldb/trunk/utils/sync-source/lib/transfer/rsync.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/utils/sync-source/lib/transfer/rsync.py?rev=247903&view=auto
==============================================================================
--- lldb/trunk/utils/sync-source/lib/transfer/rsync.py (added)
+++ lldb/trunk/utils/sync-source/lib/transfer/rsync.py Thu Sep 17 12:14:31 2015
@@ -0,0 +1,60 @@
+import os.path
+import pprint
+import subprocess
+import sys
+
+import transfer.protocol
+
+
+class RsyncOverSsh(transfer.protocol.Protocol):
+ def __init__(self, options, config):
+ super(RsyncOverSsh, self).__init__(options, config)
+ self.ssh_config = config.get_value("ssh")
+
+ def build_rsync_command(self, transfer_spec, dry_run):
+ dest_path = os.path.join(
+ self.ssh_config["root_dir"],
+ transfer_spec.dest_path)
+ flags = "-avz"
+ if dry_run:
+ flags += "n"
+ cmd = [
+ "rsync",
+ flags,
+ "-e",
+ "ssh -p {}".format(self.ssh_config["port"]),
+ "--rsync-path",
+ # The following command needs to know the right way to do
+ # this on the dest platform - ensures the target dir exists.
+ "mkdir -p {} && rsync".format(dest_path)
+ ]
+
+ # Add source dir exclusions
+ if transfer_spec.exclude_paths:
+ for exclude_path in transfer_spec.exclude_paths:
+ cmd.append("--exclude")
+ cmd.append(exclude_path)
+
+ cmd.extend([
+ "--delete",
+ transfer_spec.source_path + "/",
+ "{}@{}:{}".format(
+ self.ssh_config["user"],
+ self.ssh_config["dest_host"],
+ dest_path)])
+ return cmd
+
+ def transfer(self, transfer_specs, dry_run):
+ if self.options.verbose:
+ printer = pprint.PrettyPrinter()
+ for spec in transfer_specs:
+ printer.pprint(spec)
+
+ for spec in transfer_specs:
+ cmd = self.build_rsync_command(spec, dry_run)
+ if self.options.verbose:
+ print "executing the following command:\n{}".format(cmd)
+ result = subprocess.call(
+ cmd, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr)
+ if result != 0:
+ return result
Added: lldb/trunk/utils/sync-source/lib/transfer/transfer_spec.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/utils/sync-source/lib/transfer/transfer_spec.py?rev=247903&view=auto
==============================================================================
--- lldb/trunk/utils/sync-source/lib/transfer/transfer_spec.py (added)
+++ lldb/trunk/utils/sync-source/lib/transfer/transfer_spec.py Thu Sep 17 12:14:31 2015
@@ -0,0 +1,11 @@
+class TransferSpec(object):
+ def __init__(self, source_path, exclude_paths, dest_path):
+ self.source_path = source_path
+ self.exclude_paths = exclude_paths
+ self.dest_path = dest_path
+
+ def __repr__(self):
+ fmt = (
+ "TransferSpec(source_path='{}', exclude_paths='{}', "
+ "dest_path='{}')")
+ return fmt.format(self.source_path, self.exclude_paths, self.dest_path)
Added: lldb/trunk/utils/sync-source/pylintrc
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/utils/sync-source/pylintrc?rev=247903&view=auto
==============================================================================
--- lldb/trunk/utils/sync-source/pylintrc (added)
+++ lldb/trunk/utils/sync-source/pylintrc Thu Sep 17 12:14:31 2015
@@ -0,0 +1,2 @@
+[Master]
+init-hook='import os; import sys; sys.path.append(os.path.join(os.getcwd(), "lib")); print("hello from {}".format(os.getcwd()))'
Added: lldb/trunk/utils/sync-source/sync-source.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/utils/sync-source/sync-source.py?rev=247903&view=auto
==============================================================================
--- lldb/trunk/utils/sync-source/sync-source.py (added)
+++ lldb/trunk/utils/sync-source/sync-source.py Thu Sep 17 12:14:31 2015
@@ -0,0 +1,261 @@
+#!/usr/bin/env python
+"""
+ The LLVM Compiler Infrastructure
+
+This file is distributed under the University of Illinois Open Source
+License. See LICENSE.TXT for details.
+
+Sync lldb and related source from a local machine to a remote machine.
+
+This facilitates working on the lldb sourcecode on multiple machines
+and multiple OS types, verifying changes across all.
+"""
+
+import argparse
+import cStringIO
+import importlib
+import json
+import os.path
+import re
+import sys
+
+# Add the local lib directory to the python path.
+LOCAL_LIB_PATH = os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ "lib")
+sys.path.append(LOCAL_LIB_PATH)
+
+import transfer.transfer_spec
+
+
+DOTRC_BASE_FILENAME = ".sync-sourcerc"
+
+
+class Configuration(object):
+ """Provides chaining configuration lookup."""
+ def __init__(self, rcdata_configs):
+ self.__rcdata_configs = rcdata_configs
+
+ def get_value(self, key):
+ """
+ Return the first value in the parent chain that has the key.
+
+ The traversal starts from the most derived configuration (i.e.
+ child) and works all the way up the parent chain.
+
+ @return the value of the first key in the parent chain that
+ contains a value for the given key.
+ """
+ for config in self.__rcdata_configs:
+ if key in config:
+ return config[key]
+ return None
+
+ def __getitem__(self, key):
+ value = self.get_value(key)
+ if value:
+ return value
+ else:
+ raise KeyError(key)
+
+
+def parse_args():
+ """@return options parsed from the command line."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "--config-name", "-c", action="store", default="default",
+ help="specify configuration name to use")
+ parser.add_argument(
+ "--default-excludes", action="store", default="*.git,*.svn,*.pyc",
+ help=("comma-separated list of default file patterns to exclude "
+ "from each source directory and to protect from deletion "
+ "on each destination directory; if starting with forward "
+ "slash, it only matches at the top of the base directory"))
+ parser.add_argument(
+ "--dry-run", "-n", action="store_true",
+ help="do a dry run of the transfer operation, don't really transfer")
+ parser.add_argument(
+ "--rc-file", "-r", action="store",
+ help="specify the sync-source rc file to use for configurations")
+ parser.add_argument(
+ "--verbose", "-v", action="store_true", help="turn on verbose output")
+ return parser.parse_args()
+
+
+def read_rcfile(filename):
+ """Returns the json-parsed contents of the input file."""
+
+ # First parse file contents, removing all comments but
+ # preserving the line count.
+ regex = re.compile(r"#.*$")
+
+ comment_stripped_file = cStringIO.StringIO()
+ with open(filename, "r") as json_file:
+ for line in json_file:
+ comment_stripped_file.write(regex.sub("", line))
+ return json.load(cStringIO.StringIO(comment_stripped_file.getvalue()))
+
+
+def find_appropriate_rcfile(options):
+ # Use an options-specified rcfile if specified.
+ if options.rc_file and len(options.rc_file) > 0:
+ if not os.path.isfile(options.rc_file):
+ # If it doesn't exist, error out here.
+ raise "rcfile '{}' specified but doesn't exist".format(
+ options.rc_file)
+ return options.rc_file
+
+ # Check if current directory .sync-sourcerc exists. If so, use it.
+ local_rc_filename = os.path.abspath(DOTRC_BASE_FILENAME)
+ if os.path.isfile(local_rc_filename):
+ return local_rc_filename
+
+ # Check if home directory .sync-sourcerc exists. If so, use it.
+ homedir_rc_filename = os.path.abspath(
+ os.path.join(os.path.expanduser("~"), DOTRC_BASE_FILENAME))
+ if os.path.isfile(homedir_rc_filename):
+ return homedir_rc_filename
+
+ # Nothing matched. We don't have an rc filename candidate.
+ return None
+
+
+def get_configuration(options, rcdata, config_name):
+ rcdata_configs = []
+ next_config_name = config_name
+ while next_config_name:
+ # Find the next rcdata configuration for the given name.
+ rcdata_config = next(
+ config for config in rcdata["configurations"]
+ if config["name"] == next_config_name)
+
+ # See if we found it.
+ if rcdata_config:
+ # This is our next configuration to use in the chain.
+ rcdata_configs.append(rcdata_config)
+
+ # If we have a parent, check that next.
+ if "parent" in rcdata_config:
+ next_config_name = rcdata_config["parent"]
+ else:
+ next_config_name = None
+ else:
+ raise "failed to find specified parent config '{}'".format(
+ next_config_name)
+ return Configuration(rcdata_configs)
+
+
+def create_transfer_agent(options, configuration):
+ transfer_class_spec = configuration.get_value("transfer_class")
+ if options.verbose:
+ print "specified transfer class: '{}'".format(transfer_class_spec)
+
+ # Load the module (possibly package-qualified).
+ components = transfer_class_spec.split(".")
+ module = importlib.import_module(".".join(components[:-1]))
+
+ # Create the class name we need to load.
+ clazz = getattr(module, components[-1])
+ return clazz(options, configuration)
+
+
+def sync_configured_sources(options, configuration, default_excludes):
+ # Look up the transfer method.
+ transfer_agent = create_transfer_agent(options, configuration)
+
+ # For each configured dir_names source, do the following transfer:
+ # 1. Start with base_dir + {source-dir-name}_dir
+ # 2. Copy all files recursively, but exclude
+ # all dirs specified by source_excludes:
+ # skip all base_dir + {source-dir-name}_dir +
+ # {source-dir-name}_dir excludes.
+ source_dirs = configuration.get_value("source")
+ source_excludes = configuration.get_value("source_excludes")
+ dest_dirs = configuration.get_value("dest")
+
+ source_base_dir = source_dirs["base_dir"]
+ dest_base_dir = dest_dirs["base_dir"]
+ dir_ids = configuration.get_value("dir_names")
+ transfer_specs = []
+
+ for dir_id in dir_ids:
+ dir_key = "{}_dir".format(dir_id)
+
+ # Build the source dir (absolute) that we're copying from.
+ # Defaults the base-relative source dir to the source id (e.g. lldb)
+ rel_source_dir = source_dirs.get(dir_key, dir_id)
+ transfer_source_dir = os.path.expanduser(
+ os.path.join(source_base_dir, rel_source_dir))
+
+ # Exclude dirs do two things:
+ # 1) stop items from being copied on the source side, and
+ # 2) protect things from being deleted on the dest side.
+ #
+ # In both cases, they are specified relative to the base
+ # directory on either the source or dest side.
+ #
+ # Specifying a leading '/' in the directory will limit it to
+ # be rooted in the base directory. i.e. "/.git" will only
+ # match {base-dir}/.git, not {base-dir}/subdir/.git, but
+ # ".svn" will match {base-dir}/.svn and
+ # {base-dir}/subdir/.svn.
+ #
+ # If excludes are specified for this dir_id, then pass along
+ # the excludes. These are relative to the dir_id directory
+ # source, and get passed along that way as well.
+ transfer_source_excludes = list(default_excludes)
+ if source_excludes and dir_key in source_excludes:
+ transfer_source_excludes.extend(source_excludes[dir_key])
+
+ # Build the destination-base-relative dest dir into which
+ # we'll be syncing. Relative directory defaults to the
+ # dir id
+ rel_dest_dir = dest_dirs.get(dir_key, dir_id)
+ transfer_dest_dir = os.path.join(dest_base_dir, rel_dest_dir)
+
+ # Add the exploded paths to the list that we'll ask the
+ # transfer agent to transfer for us.
+ transfer_specs.append(
+ transfer.transfer_spec.TransferSpec(
+ transfer_source_dir,
+ transfer_source_excludes,
+ transfer_dest_dir))
+
+ # Do the transfer.
+ if len(transfer_specs) > 0:
+ transfer_agent.transfer(transfer_specs, options.dry_run)
+ else:
+ raise "nothing to transfer, bad configuration?"
+
+
+def main():
+ """Drives the main program."""
+ options = parse_args()
+
+ if options.default_excludes and len(options.default_excludes) > 0:
+ default_excludes = options.default_excludes.split(",")
+ else:
+ default_excludes = []
+
+ # Locate the rc filename to load, then load it.
+ rc_filename = find_appropriate_rcfile(options)
+ if rc_filename:
+ if options.verbose:
+ print "reading rc data from file '{}'".format(rc_filename)
+ rcdata = read_rcfile(rc_filename)
+ else:
+ sys.stderr.write("no rcfile specified, cannot guess configuration")
+ exit(1)
+
+ # Find configuration.
+ configuration = get_configuration(options, rcdata, options.config_name)
+ if not configuration:
+ sys.stderr.write("failed to find configuration for {}".format(
+ options.config_data))
+ exit(2)
+
+ # Kick off the transfer.
+ sync_configured_sources(options, configuration, default_excludes)
+
+if __name__ == "__main__":
+ main()
More information about the lldb-commits
mailing list