X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=cdist;h=3bf9460a9690dcda316e339e2f8cecc6e568004f;hb=0240aabb334ab482b0a2d96ce32d19fc94a3e9fe;hp=2dffac8a90b24601473fbce7141ecbe2b783528a;hpb=f3bdda1e966c3e873d063683191e14bff67d764d;p=cdist.git diff --git a/cdist b/cdist index 2dffac8..3bf9460 100755 --- a/cdist +++ b/cdist @@ -1,6 +1,6 @@ #!/usr/bin/python -# Copyright (C) 2012-2014 Carl Hetherington +# Copyright (C) 2012-2015 Carl Hetherington # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -28,13 +28,7 @@ import re import copy import inspect -TEMPORARY_DIRECTORY = '/tmp' - -class Globals: - quiet = False - command = None - -globals = Globals() +TEMPORARY_DIRECTORY = '/var/tmp' class Error(Exception): def __init__(self, value): @@ -44,6 +38,34 @@ class Error(Exception): def __repr__(self): return str(self) +class Trees: + """ + Store for Tree objects which re-uses already-created objects + and checks for requests for different versions of the same thing. + """ + + def __init__(self): + self.trees = [] + + def get(self, name, specifier, target): + for t in self.trees: + if t.name == name and t.specifier == specifier and t.target == target: + return t + elif t.name == name and t.specifier != specifier: + raise Error('conflicting versions of %s requested (%s and %s)' % (name, specifier, t.specifier)) + + nt = Tree(name, specifier, target) + self.trees.append(nt) + return nt + +class Globals: + quiet = False + command = None + trees = Trees() + +globals = Globals() + + # # Configuration # @@ -102,23 +124,42 @@ class Config: raise Error('Required setting %s not found' % k) + def set(self, k, v): + for o in self.options: + o.offer(k, v) + config = Config() # # Utility bits -# +# def log(m): if not globals.quiet: print '\x1b[33m* %s\x1b[0m' % m +def scp_escape(n): + s = n.split(':') + assert(len(s) == 1 or len(s) == 2) + if len(s) == 2: + return '%s:"\'%s\'"' % (s[0], s[1]) + else: + return '\"%s\"' % s[0] + def copytree(a, b): - log('copy %s -> %s' % (a, b)) - os.command('scp -r %s %s' % (a, b)) + log('copy %s -> %s' % (scp_escape(b), scp_escape(b))) + command('scp -r %s %s' % (scp_escape(a), scp_escape(b))) def copyfile(a, b): - log('copy %s -> %s' % (a, b)) - os.command('scp %s %s' % (a, b)) + log('copy %s -> %s' % (scp_escape(a), scp_escape(b))) + command('scp %s %s' % (scp_escape(a), scp_escape(b))) + +def makedirs(d): + if d.find(':') == -1: + os.makedirs(d) + else: + s = d.split(':') + command('ssh %s -- mkdir -p %s' % (s[0], s[1])) def rmdir(a): log('remove %s' % a) @@ -128,10 +169,10 @@ def rmtree(a): log('remove %s' % a) shutil.rmtree(a, ignore_errors=True) -def command(c, can_fail=False): +def command(c): log(c) r = os.system(c) - if (r >> 8) and not can_fail: + if (r >> 8): raise Error('command %s failed' % c) def command_and_read(c): @@ -146,7 +187,7 @@ def read_wscript_variable(directory, variable): l = f.readline() if l == '': break - + s = l.split() if len(s) == 3 and s[0] == variable: f.close() @@ -155,6 +196,61 @@ def read_wscript_variable(directory, variable): f.close() return None +def set_version_in_wscript(version): + f = open('wscript', 'rw') + o = open('wscript.tmp', 'w') + while True: + l = f.readline() + if l == '': + break + + s = l.split() + if len(s) == 3 and s[0] == "VERSION": + print "Writing %s" % version + print >>o,"VERSION = '%s'" % version + else: + print >>o,l, + f.close() + o.close() + + os.rename('wscript.tmp', 'wscript') + +def append_version_to_changelog(version): + try: + f = open('ChangeLog', 'r') + except: + log('Could not open ChangeLog') + return + + c = f.read() + f.close() + + f = open('ChangeLog', 'w') + now = datetime.datetime.now() + f.write('%d-%02d-%02d Carl Hetherington \n\n\t* Version %s released.\n\n' % (now.year, now.month, now.day, version)) + f.write(c) + +def append_version_to_debian_changelog(version): + if not os.path.exists('debian'): + log('Could not find debian directory') + return + + command('dch -b -v %s-1 "New upstream release."' % version) + +def devel_to_git(git_commit, filename): + if git_commit is not None: + filename = filename.replace('devel', '-%s' % git_commit) + return filename + +class TreeDirectory: + def __init__(self, tree): + self.tree = tree + def __enter__(self): + self.cwd = os.getcwd() + os.chdir('%s/src/%s' % (self.tree.target.directory, self.tree.name)) + def __exit__(self, type, value, traceback): + os.chdir(self.cwd) + # # Version # @@ -167,7 +263,7 @@ class Version: s = s[1:] if s.endswith("'"): s = s[0:-1] - + if s.endswith('devel'): s = s[0:-5] self.devel = True @@ -208,12 +304,16 @@ class Version: # class Target(object): - # @param directory directory to work in; if None we will use a temporary directory - # Temporary directories will be removed after use; specified directories will not + """ + platform -- platform string (e.g. 'windows', 'linux', 'osx') + directory -- directory to work in; if None we will use a temporary directory + Temporary directories will be removed after use; specified directories will not. + """ def __init__(self, platform, directory=None): self.platform = platform self.parallel = int(config.get('parallel')) + # self.directory is the working directory if directory is None: self.directory = tempfile.mkdtemp('', 'tmp', TEMPORARY_DIRECTORY) self.rmdir = True @@ -225,47 +325,16 @@ class Target(object): self.variables = {} self.debug = False - def build_dependencies(self, project): - cwd = os.getcwd() - if 'dependencies' in project.cscript: - for d in project.cscript['dependencies'](self): - log('Building dependency %s %s of %s' % (d[0], d[1], project.name)) - dep = Project(d[0], '.', d[1]) - dep.checkout(self) - self.build_dependencies(dep) - - # Make the options to pass in from the option_defaults of the thing - # we are building and any options specified by the parent. - options = {} - if 'option_defaults' in dep.cscript: - options = dep.cscript['option_defaults']() - if len(d) > 2: - for k, v in d[2].iteritems(): - options[k] = v + def package(self, project, checkout): + tree = globals.trees.get(project, checkout, self) + tree.build_dependencies() + tree.build(tree) + return tree.call('package', tree.version), tree.git_commit - self.build(dep, options) - - os.chdir(cwd) - - def build(self, project, options=None): - variables = copy.copy(self.variables) - if len(inspect.getargspec(project.cscript['build']).args) == 2: - project.cscript['build'](self, options) - else: - project.cscript['build'](self) - self.variables = variables - - def package(self, project): - project.checkout(self) - self.build_dependencies(project) - self.build(project) - return project.cscript['package'](self, project.version) - - def test(self, project): - project.checkout(self) - self.build_dependencies(project) - self.build(project) - project.cscript['test'](self) + def test(self, tree): + tree.build_dependencies() + tree.build() + return tree.call('test') def set(self, a, b): self.variables[a] = b @@ -277,10 +346,14 @@ class Target(object): return self.variables[a] def append_with_space(self, k, v): - if not k in self.variables: - self.variables[k] = v + if (not k in self.variables) or len(self.variables[k]) == 0: + self.variables[k] = '"%s"' % v else: - self.variables[k] = '%s %s' % (self.variables[k], v) + e = self.variables[k] + if e[0] == '"' and e[-1] == '"': + self.variables[k] = '"%s %s"' % (e[1:-1], v) + else: + self.variables[k] = '"%s %s"' % (e, v) def variables_string(self, escaped_quotes=False): e = '' @@ -294,7 +367,7 @@ class Target(object): if self.rmdir: rmtree(self.directory) -# +# # Windows # @@ -306,18 +379,18 @@ class WindowsTarget(Target): self.windows_prefix = '%s/%d' % (config.get('windows_environment_prefix'), self.bits) if not os.path.exists(self.windows_prefix): raise Error('windows prefix %s does not exist' % self.windows_prefix) - + if self.bits == 32: self.mingw_name = 'i686' else: self.mingw_name = 'x86_64' - mingw_path = '%s/%d/bin' % (config.get('mingw_prefix'), self.bits) + self.mingw_path = '%s/%d/bin' % (config.get('mingw_prefix'), self.bits) self.mingw_prefixes = ['/%s/%d' % (config.get('mingw_prefix'), self.bits), '%s/%d/%s-w64-mingw32' % (config.get('mingw_prefix'), bits, self.mingw_name)] self.set('PKG_CONFIG_LIBDIR', '%s/lib/pkgconfig' % self.windows_prefix) self.set('PKG_CONFIG_PATH', '%s/lib/pkgconfig:%s/bin/pkgconfig' % (self.directory, self.directory)) - self.set('PATH', '%s/bin:%s:%s' % (self.windows_prefix, mingw_path, os.environ['PATH'])) + self.set('PATH', '%s/bin:%s:%s' % (self.windows_prefix, self.mingw_path, os.environ['PATH'])) self.set('CC', '%s-w64-mingw32-gcc' % self.mingw_name) self.set('CXX', '%s-w64-mingw32-g++' % self.mingw_name) self.set('LD', '%s-w64-mingw32-ld' % self.mingw_name) @@ -331,35 +404,50 @@ class WindowsTarget(Target): self.set('CXXFLAGS', '"%s"' % cxx) self.set('CPPFLAGS', '') self.set('LINKFLAGS', '"%s"' % link) + self.set('LDFLAGS', '"%s"' % link) def command(self, c): log('host -> %s' % c) command('%s %s' % (self.variables_string(), c)) -# -# Linux -# - class LinuxTarget(Target): + """Parent for Linux targets""" def __init__(self, distro, version, bits, directory=None): super(LinuxTarget, self).__init__('linux', directory) self.distro = distro self.version = version self.bits = bits - # e.g. ubuntu-14.04-64 - self.chroot = '%s-%s-%d' % (self.distro, self.version, self.bits) - # e.g. /home/carl/Environments/ubuntu-14.04-64 - self.chroot_prefix = '%s/%s' % (config.get('linux_chroot_prefix'), self.chroot) self.set('CXXFLAGS', '-I%s/include' % self.directory) self.set('CPPFLAGS', '') self.set('LINKFLAGS', '-L%s/lib' % self.directory) self.set('PKG_CONFIG_PATH', '%s/lib/pkgconfig:/usr/local/lib/pkgconfig' % self.directory) - self.set('PATH', '%s:/usr/local/bin' % (os.environ['PATH'])) + self.set('PATH', '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin') + +class ChrootTarget(LinuxTarget): + """Build in a chroot""" + def __init__(self, distro, version, bits, directory=None): + super(ChrootTarget, self).__init__(distro, version, bits, directory) + # e.g. ubuntu-14.04-64 + if self.version is not None and self.bits is not None: + self.chroot = '%s-%s-%d' % (self.distro, self.version, self.bits) + else: + self.chroot = self.distro + # e.g. /home/carl/Environments/ubuntu-14.04-64 + self.chroot_prefix = '%s/%s' % (config.get('linux_chroot_prefix'), self.chroot) def command(self, c): command('%s schroot -c %s -p -- %s' % (self.variables_string(), self.chroot, c)) + +class HostTarget(LinuxTarget): + """Build directly on the host""" + def __init__(self, distro, version, bits, directory=None): + super(HostTarget, self).__init__(distro, version, bits, directory) + + def command(self, c): + command('%s %s' % (self.variables_string(), c)) + # # OS X # @@ -367,6 +455,8 @@ class LinuxTarget(Target): class OSXTarget(Target): def __init__(self, directory=None): super(OSXTarget, self).__init__('osx', directory) + self.sdk = config.get('osx_sdk') + self.sdk_prefix = config.get('osx_sdk_prefix') def command(self, c): command('%s %s' % (self.variables_string(False), c)) @@ -382,7 +472,7 @@ class OSXSingleTarget(OSXTarget): else: arch = 'x86_64' - flags = '-isysroot %s/MacOSX%s.sdk -arch %s' % (config.get('osx_sdk_prefix'), config.get('osx_sdk'), arch) + flags = '-isysroot %s/MacOSX%s.sdk -arch %s' % (self.sdk_prefix, self.osx_sdk, arch) enviro = '%s/%d' % (config.get('osx_environment_prefix'), bits) # Environment variables @@ -395,31 +485,28 @@ class OSXSingleTarget(OSXTarget): self.set('PATH', '$PATH:/usr/bin:/sbin:/usr/local/bin:%s/bin' % enviro) self.set('MACOSX_DEPLOYMENT_TARGET', config.get('osx_sdk')) - def package(self, project): + def package(self, project, checkout): raise Error('cannot package non-universal OS X versions') class OSXUniversalTarget(OSXTarget): def __init__(self, directory=None): super(OSXUniversalTarget, self).__init__(directory) - self.parts = [] - self.parts.append(OSXSingleTarget(32, os.path.join(self.directory, '32'))) - self.parts.append(OSXSingleTarget(64, os.path.join(self.directory, '64'))) - def package(self, project): - for p in self.parts: - project.checkout(p) - p.build_dependencies(project) - p.build(project) + def package(self, project, checkout): - return project.cscript['package'](self, project.version) - + for b in [32, 64]: + target = OSXSingleTarget(b, os.path.join(self.directory, '%d' % b)) + tree = globals.trees.get(project, checkout, target) + tree.build_dependencies() + tree.build() -# -# Source -# + tree = globals.trees.get(project, checkout, self) + with TreeDirectory(tree): + return tree.call('package', tree.version), tree.git_commit class SourceTarget(Target): + """Build a source .tar.bz2""" def __init__(self): super(SourceTarget, self).__init__('source') @@ -430,11 +517,12 @@ class SourceTarget(Target): def cleanup(self): rmtree(self.directory) - def package(self, project): - project.checkout(self) - name = read_wscript_variable(os.getcwd(), 'APPNAME') - command('./waf dist') - return os.path.abspath('%s-%s.tar.bz2' % (name, project.version)) + def package(self, project, checkout): + tree = globals.trees.get(project, checkout, self) + with TreeDirectory(tree): + name = read_wscript_variable(os.getcwd(), 'APPNAME') + command('./waf dist') + return os.path.abspath('%s-%s.tar.bz2' % (name, tree.version)), tree.git_commit # @param s Target string: @@ -443,7 +531,7 @@ class SourceTarget(Target): # or debian-version-{32,64} # or centos-version-{32,64} # or osx-{32,64} -# or source +# or source # @param debug True to build with debugging symbols (where possible) def target_factory(s, debug, work): target = None @@ -452,9 +540,21 @@ def target_factory(s, debug, work): elif s.startswith('ubuntu-') or s.startswith('debian-') or s.startswith('centos-'): p = s.split('-') if len(p) != 3: - print >>sys.stderr,"Bad Linux target name `%s'; must be something like ubuntu-12.04-32 (i.e. distro-version-bits)" % s - sys.exit(1) - target = LinuxTarget(p[0], p[1], int(p[2]), work) + raise Error("Bad Linux target name `%s'; must be something like ubuntu-12.04-32 (i.e. distro-version-bits)" % s) + target = ChrootTarget(p[0], p[1], int(p[2]), work) + elif s == 'raspbian': + target = ChrootTarget(s, None, None, work) + elif s == 'host': + try: + f = open('/etc/fedora-release', 'r') + l = f.readline().strip().split() + if command_and_read('uname -m').read().strip() == 'x86_64': + bits = 64 + else: + bits = 32 + target = HostTarget("fedora", l[2], bits, work) + except Exception as e: + raise Error("could not identify distribution for `host' target (%s)" % e) elif s.startswith('osx-'): target = OSXSingleTarget(int(s.split('-')[1]), work) elif s == 'osx': @@ -465,27 +565,39 @@ def target_factory(s, debug, work): elif s == 'source': target = SourceTarget() - if target is not None: - target.debug = debug + if target is None: + raise Error("Bad target `%s'" % s) + target.debug = debug return target # -# Project +# Tree # - -class Project(object): - def __init__(self, name, directory, specifier=None): + +class Tree(object): + """Description of a tree, which is a checkout of a project, + possibly built. This class is never exposed to cscripts. + Attributes: + name -- name of git repository (without the .git) + specifier -- git tag or revision to use + target --- target object that we are using + version --- version from the wscript (if one is present) + git_commit -- git revision that is actually being used + built --- true if the tree has been built yet in this run + """ + + def __init__(self, name, specifier, target): self.name = name - self.directory = directory - self.version = None self.specifier = specifier + self.target = target + self.version = None self.git_commit = None - if self.specifier is None: - self.specifier = 'master' + self.built = False + + cwd = os.getcwd() - def checkout(self, target): flags = '' redirect = '' if globals.quiet: @@ -493,71 +605,63 @@ class Project(object): redirect = '>/dev/null' command('git clone %s %s/%s.git %s/src/%s' % (flags, config.get('git_prefix'), self.name, target.directory, self.name)) os.chdir('%s/src/%s' % (target.directory, self.name)) - command('git checkout %s %s %s' % (flags, self.specifier, redirect)) + + spec = self.specifier + if spec is None: + spec = 'master' + + command('git checkout %s %s %s' % (flags, spec, redirect)) self.git_commit = command_and_read('git rev-parse --short=7 HEAD').readline().strip() command('git submodule init --quiet') command('git submodule update --quiet') - os.chdir(self.directory) - proj = '%s/src/%s/%s' % (target.directory, self.name, self.directory) + proj = '%s/src/%s' % (target.directory, self.name) + + self.cscript = {} + execfile('%s/cscript' % proj, self.cscript) - self.read_cscript('%s/cscript' % proj) - if os.path.exists('%s/wscript' % proj): v = read_wscript_variable(proj, "VERSION"); if v is not None: self.version = Version(v) - def read_cscript(self, s): - self.cscript = {} - execfile(s, self.cscript) - -def set_version_in_wscript(version): - f = open('wscript', 'rw') - o = open('wscript.tmp', 'w') - while True: - l = f.readline() - if l == '': - break - - s = l.split() - if len(s) == 3 and s[0] == "VERSION": - print "Writing %s" % version - print >>o,"VERSION = '%s'" % version - else: - print >>o,l, - f.close() - o.close() + os.chdir(cwd) - os.rename('wscript.tmp', 'wscript') + def call(self, function, *args): + with TreeDirectory(self): + return self.cscript[function](self.target, *args) -def append_version_to_changelog(version): - try: - f = open('ChangeLog', 'r') - except: - log('Could not open ChangeLog') - return + def build_dependencies(self): + if 'dependencies' in self.cscript: + for d in self.cscript['dependencies'](self.target): + log('Building dependency %s %s of %s' % (d[0], d[1], self.name)) + dep = globals.trees.get(d[0], d[1], self.target) + dep.build_dependencies() - c = f.read() - f.close() + # Make the options to pass in from the option_defaults of the thing + # we are building and any options specified by the parent. + options = {} + if 'option_defaults' in dep.cscript: + options = dep.cscript['option_defaults']() + if len(d) > 2: + for k, v in d[2].iteritems(): + options[k] = v - f = open('ChangeLog', 'w') - now = datetime.datetime.now() - f.write('%d-%02d-%02d Carl Hetherington \n\n\t* Version %s released.\n\n' % (now.year, now.month, now.day, version)) - f.write(c) + dep.build(options) -def append_version_to_debian_changelog(version): - if not os.path.exists('debian'): - log('Could not find debian directory') - return + def build(self, options=None): + if self.built: + return - command('dch -b -v %s-1 "New upstream release."' % version) + variables = copy.copy(self.target.variables) -def devel_to_git(project, filename): - if project.git_commit is not None: - filename = filename.replace('devel', '-%s' % project.git_commit) - return filename + if len(inspect.getargspec(self.cscript['build']).args) == 2: + self.call('build', options) + else: + self.call('build') + self.target.variables = variables + self.built = True # # Command-line parser @@ -576,6 +680,7 @@ def main(): "latest": "print out the latest version", "test": "run the project's unit tests", "shell": "build the project then start a shell in its chroot", + "checkout": "check out the project", "revision": "print the head git revision number" } @@ -588,7 +693,6 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument('command', help=summary) parser.add_argument('-p', '--project', help='project name') - parser.add_argument('-d', '--directory', help='directory within project repo', default='.') parser.add_argument('--minor', help='minor version number bump', action='store_true') parser.add_argument('--micro', help='micro version number bump', action='store_true') parser.add_argument('--major', help='major version to return with latest', type=int) @@ -599,20 +703,31 @@ def main(): parser.add_argument('-k', '--keep', help='keep working tree', action='store_true') parser.add_argument('--debug', help='build with debugging symbols where possible', action='store_true') parser.add_argument('-w', '--work', help='override default work directory') + parser.add_argument('-g', '--git-prefix', help='override configured git prefix') args = parser.parse_args() - args.output = os.path.abspath(args.output) + # Override configured stuff + if args.git_prefix is not None: + config.set('git_prefix', args.git_prefix) + + if args.output.find(':') == -1: + # This isn't of the form host:path so make it absolute + args.output = os.path.abspath(args.output) + '/' + else: + if args.output[-1] != ':' and args.output[-1] != '/': + args.output += '/' + + # Now, args.output is 'host:', 'host:path/' or 'path/' + if args.work is not None: args.work = os.path.abspath(args.work) if args.project is None and args.command != 'shell': raise Error('you must specify -p or --project') - + globals.quiet = args.quiet globals.command = args.command - project = Project(args.project, args.directory, args.checkout) - if not globals.command in commands: e = 'command must be one of:\n' + one_of raise Error('command must be one of:\n%s' % one_of) @@ -622,9 +737,9 @@ def main(): raise Error('you must specify -t or --target') target = target_factory(args.target, args.debug, args.work) - project.checkout(target) - target.build_dependencies(project) - target.build(project) + tree = globals.trees.get(args.project, args.checkout, target) + tree.build_dependencies() + tree.build() if not args.keep: target.cleanup() @@ -633,22 +748,25 @@ def main(): raise Error('you must specify -t or --target') target = target_factory(args.target, args.debug, args.work) - - packages = target.package(project) + packages, git_commit = target.package(args.project, args.checkout) if hasattr(packages, 'strip') or (not hasattr(packages, '__getitem__') and not hasattr(packages, '__iter__')): packages = [packages] if target.platform == 'linux': - out = '%s/%s-%s-%d' % (args.output, target.distro, target.version, target.bits) + out = '%s%s-%s-%d' % (args.output, target.distro, target.version, target.bits) try: - os.makedirs(out) + makedirs(out) except: pass for p in packages: - copyfile(p, '%s/%s' % (out, os.path.basename(devel_to_git(project, p)))) + copyfile(p, '%s/%s' % (out, os.path.basename(devel_to_git(git_commit, p)))) else: + try: + makedirs(args.output) + except: + pass for p in packages: - copyfile(p, '%s/%s' % (args.output, os.path.basename(devel_to_git(project, p)))) + copyfile(p, '%s%s' % (args.output, os.path.basename(devel_to_git(git_commit, p)))) if not args.keep: target.cleanup() @@ -658,9 +776,9 @@ def main(): raise Error('you must specify --minor or --micro') target = SourceTarget() - project.checkout(target) + tree = globals.trees.get(args.project, args.checkout, target) - version = project.version + version = tree.version version.to_release() if args.minor: version.bump_minor() @@ -684,19 +802,21 @@ def main(): elif globals.command == 'pot': target = SourceTarget() - project.checkout(target) + tree = globals.trees.get(args.project, args.checkout, target) - pots = project.cscript['make_pot'](target) + pots = tree.call('make_pot') for p in pots: - copyfile(p, '%s/%s' % (args.output, os.path.basename(p))) + copyfile(p, '%s%s' % (args.output, os.path.basename(p))) target.cleanup() elif globals.command == 'changelog': target = SourceTarget() - project.checkout(target) + tree = globals.trees.get(args.project, args.checkout, target) + + with TreeDirectory(tree): + text = open('ChangeLog', 'r') - text = open('ChangeLog', 'r') html = tempfile.NamedTemporaryFile() versions = 8 @@ -732,55 +852,56 @@ def main(): else: changes[-1] += " " + c - copyfile(html.file, '%s/changelog.html' % args.output) + copyfile(html.file, '%schangelog.html' % args.output) html.close() target.cleanup() elif globals.command == 'manual': target = SourceTarget() - project.checkout(target) + tree = globals.trees.get(args.project, args.checkout, target) - outs = project.cscript['make_manual'](target) + outs = tree.call('make_manual') for o in outs: if os.path.isfile(o): - copyfile(o, '%s/%s' % (args.output, os.path.basename(o))) + copyfile(o, '%s%s' % (args.output, os.path.basename(o))) else: - copytree(o, '%s/%s' % (args.output, os.path.basename(o))) + copytree(o, '%s%s' % (args.output, os.path.basename(o))) target.cleanup() elif globals.command == 'doxygen': target = SourceTarget() - project.checkout(target) + tree = globals.trees.get(args.project, args.checkout, target) - dirs = project.cscript['make_doxygen'](target) + dirs = tree.call('make_doxygen') if hasattr(dirs, 'strip') or (not hasattr(dirs, '__getitem__') and not hasattr(dirs, '__iter__')): dirs = [dirs] for d in dirs: - copytree(d, '%s/%s' % (args.output, 'doc')) + copytree(d, args.output) target.cleanup() elif globals.command == 'latest': target = SourceTarget() - project.checkout(target) - - f = command_and_read('git log --tags --simplify-by-decoration --pretty="%d"') - latest = None - while latest is None: - t = f.readline() - m = re.compile(".*\((.*)\).*").match(t) - if m: - tags = m.group(1).split(', ') - for t in tags: - s = t.split() - if len(s) > 1: - t = s[1] - if len(t) > 0 and t[0] == 'v': - v = Version(t[1:]) - if args.major is None or v.major == args.major: - latest = v + tree = globals.trees.get(args.project, args.checkout, target) + + with TreeDirectory(tree): + f = command_and_read('git log --tags --simplify-by-decoration --pretty="%d"') + latest = None + while latest is None: + t = f.readline() + m = re.compile(".*\((.*)\).*").match(t) + if m: + tags = m.group(1).split(', ') + for t in tags: + s = t.split() + if len(s) > 1: + t = s[1] + if len(t) > 0 and t[0] == 'v': + v = Version(t[1:]) + if args.major is None or v.major == args.major: + latest = v print latest target.cleanup() @@ -792,7 +913,9 @@ def main(): target = None try: target = target_factory(args.target, args.debug, args.work) - target.test(project) + tree = globals.trees.get(args.project, args.checkout, target) + with TreeDirectory(tree): + target.test(tree) except Error as e: if target is not None: target.cleanup() @@ -811,8 +934,20 @@ def main(): elif globals.command == 'revision': target = SourceTarget() - project.checkout(target) - print command_and_read('git rev-parse HEAD').readline().strip()[:7] + tree = globals.trees.get(args.project, args.checkout, target) + with TreeDirectory(tree): + print command_and_read('git rev-parse HEAD').readline().strip()[:7] + target.cleanup() + + elif globals.command == 'checkout': + + if args.output is None: + raise Error('you must specify -o or --output') + + target = SourceTarget() + tree = globals.trees.get(args.project, args.checkout, target) + with TreeDirectory(tree): + shutil.copytree('.', args.output) target.cleanup() else: