def setupTagsDirectory(self): if self._setupTagsDirectory == None: self._setupTagsDirectory = False if self.module and self.module <> '/': # Check the existing tags directory cmd = self.command("ls") svnls = ExternalCommand(command=cmd) svnls.execute(self.repository + self.tags_path) if svnls.exit_status: # create it, if not exist cmd = self.command("mkdir", "-m", "This directory will host the tags") svnmkdir = ExternalCommand(command=cmd) svnmkdir.execute(self.repository + self.tags_path) if svnmkdir.exit_status: raise TargetInitializationFailure( "Was not able to create tags directory '%s'" % self.tags_path) else: self.log.debug("Directory '%s' already exists" % self.tags_path) self._setupTagsDirectory = True else: self.log.debug("Tags needs module setup other than '/'") return self._setupTagsDirectory
def _handleConflict(self, changeset, conflicts, conflict): """ Handle the conflict raised by the application of the upstream changeset. Override parent behaviour: with darcs, we need to execute a revert on the conflicted files, **trashing** local changes, but there should be none of them in tailor context. """ from os import walk, unlink from os.path import join from re import compile self.log.info("Reverting changes to %s, to solve the conflict", ' '.join(conflict)) cmd = self.repository.command("revert", "--all") revert = ExternalCommand(cwd=self.repository.basedir, command=cmd) revert.execute(conflict, input="\n") # Remove also the backups made by darcs bckre = compile('-darcs-backup[0-9]+$') for root, dirs, files in walk(self.repository.basedir): backups = [f for f in files if bckre.search(f)] for bck in backups: self.log.debug("Removing backup file %r in %r", bck, root) unlink(join(root, bck))
def _commit(self, date, author, patchname, changelog=None, entries=None, tags = [], isinitialcommit = False): """ Commit the changeset. """ logmessage = [] logmessage.append(date.astimezone(UTC).strftime('%Y/%m/%d %H:%M:%S UTC')) logmessage.append(author) if patchname: logmessage.append(patchname) if changelog: logmessage.append(changelog) if not patchname and not changelog: logmessage.append('Unnamed patch') cmd = self.repository.command("record", "--all", "--pipe") if not entries: entries = ['.'] record = ExternalCommand(cwd=self.repository.basedir, command=cmd) record.execute(input=self.repository.encode('\n'.join(logmessage))) if record.exit_status: raise ChangesetApplicationFailure( "%s returned status %d" % (str(record), record.exit_status))
def _commit(self, date, author, patchname, changelog=None, entries=None, tags = [], isinitialcommit = False): """ Commit the changeset. """ from vcpx.shwrap import ReopenableNamedTemporaryFile encode = self.repository.encode logmessage = [] if patchname: logmessage.append(patchname) if changelog: logmessage.append(changelog) logmessage.append('') logmessage.append('Original author: %s' % author) logmessage.append('Date: %s' % date) rontf = ReopenableNamedTemporaryFile('cvs', 'tailor') log = open(rontf.name, "w") log.write(encode('\n'.join(logmessage))) log.close() cmd = self.repository.command("-f", "-q", "ci", "-F", rontf.name) if not entries: entries = ['.'] c = ExternalCommand(cwd=self.repository.basedir, command=cmd) c.execute(entries) if c.exit_status: raise ChangesetApplicationFailure("%s returned status %d" % (str(c), c.exit_status))
def _tag(self, tagname, date, author): """ Apply a tag. """ # Sanitize tagnames for CVS: start with [a-zA-z], only include letters, # numbers, '-' and '_'. # str.isalpha et al are locale-dependent def iscvsalpha(chr): return (chr >= 'a' and chr <= 'z') or (chr >= 'A' and chr <= 'Z') def iscvsdigit(chr): return chr >= '0' and chr <= '9' def iscvschar(chr): return iscvsalpha(chr) or iscvsdigit( chr) or chr == '-' or chr == '_' def cvstagify(chr): if iscvschar(chr): return chr else: return '_' tagname = ''.join([cvstagify(chr) for chr in tagname]) if not iscvsalpha(tagname[0]): tagname = 'tag-' + tagname cmd = self.repository.command("-f", "tag") c = ExternalCommand(cwd=self.repository.basedir, command=cmd) c.execute(tagname) if c.exit_status: raise ChangesetApplicationFailure("%s returned status %d" % (str(c), c.exit_status))
def _commit(self, date, author, patchname, changelog=None, entries=None, tags = [], isinitialcommit = False): """ Commit the changeset. """ from os import environ encode = self.repository.encode logmessage = [] if patchname: logmessage.append(patchname) if changelog: logmessage.append(changelog) env = {} env.update(environ) (name, email) = self.__parse_author(author) if name: env['GIT_AUTHOR_NAME'] = encode(name) if email: env['GIT_AUTHOR_EMAIL']=email if date: env['GIT_AUTHOR_DATE']=date.strftime('%Y-%m-%d %H:%M:%S %z') # '-f' flag means we can get empty commits, which # shouldn't be a problem. cmd = self.repository.command("commit", "-f") c = ExternalCommand(cwd=self.repository.basedir, command=cmd) c.execute(env=env, input=encode('\n'.join(logmessage))) if c.exit_status: raise ChangesetApplicationFailure("%s returned status %d" % (str(c), c.exit_status))
def _commit(self, date, author, patchname, changelog=None, entries=None, tags=[], isinitialcommit=False): """ Commit the changeset. """ logmessage = [] logmessage.append( date.astimezone(UTC).strftime('%Y/%m/%d %H:%M:%S UTC')) logmessage.append(author) if patchname: logmessage.append(patchname) if changelog: logmessage.append(changelog) if not patchname and not changelog: logmessage.append('Unnamed patch') cmd = self.repository.command("record", "--all", "--pipe") if not entries: entries = ['.'] record = ExternalCommand(cwd=self.repository.basedir, command=cmd) record.execute(input=self.repository.encode('\n'.join(logmessage))) if record.exit_status: raise ChangesetApplicationFailure( "%s returned status %d" % (str(record), record.exit_status))
def _commit(self, date, author, patchname, changelog=None, entries=None, tags=[], isinitialcommit=False): """ Commit the changeset. """ encode = self.repository.encode logmessage = [] if patchname: logmessage.append(patchname) if changelog: logmessage.append(changelog.replace('%', '%%')) cmd = self.repository.command("commit", "-s", encode('\n'.join(logmessage)), "--author", encode(author), "--date", date.isoformat()) c = ExternalCommand(cwd=self.repository.basedir, command=cmd) c.execute() if c.exit_status: raise ChangesetApplicationFailure("%s returned status %d" % (str(c), c.exit_status))
def _commit(self, date, author, patchname, changelog=None, entries=None, tags = [], isinitialcommit = False): """ Commit the changeset. """ encode = self.repository.encode logmessage = [] if patchname: logmessage.append(patchname) if changelog: logmessage.append(changelog.replace('%', '%%')) cmd = self.repository.command("-u", encode(author), "commit", "-m", encode('\n'.join(logmessage)), "-D", date.astimezone(UTC).strftime('%Y/%m/%d %H:%M:%S UTC')) if not entries: entries = ['...'] c = ExternalCommand(cwd=self.repository.basedir, command=cmd) c.execute(entries) if c.exit_status: raise ChangesetApplicationFailure("%s returned status %d" % (str(c), c.exit_status))
def _tag(self, tagname, date, author): """ Apply a tag. """ # Sanitize tagnames for CVS: start with [a-zA-z], only include letters, # numbers, '-' and '_'. # str.isalpha et al are locale-dependent def iscvsalpha(chr): return (chr >= 'a' and chr <= 'z') or (chr >= 'A' and chr <= 'Z') def iscvsdigit(chr): return chr >= '0' and chr <= '9' def iscvschar(chr): return iscvsalpha(chr) or iscvsdigit(chr) or chr == '-' or chr == '_' def cvstagify(chr): if iscvschar(chr): return chr else: return '_' tagname = ''.join([cvstagify(chr) for chr in tagname]) if not iscvsalpha(tagname[0]): tagname = 'tag-' + tagname cmd = self.repository.command("-f", "tag") c = ExternalCommand(cwd=self.repository.basedir, command=cmd) c.execute(tagname) if c.exit_status: raise ChangesetApplicationFailure("%s returned status %d" % (str(c), c.exit_status))
def _prepareWorkingDirectory(self, source_repo): """ Checkout a working copy of the target SVN repository. """ from os.path import join, exists from vcpx.dualwd import IGNORED_METADIRS if not self.repository.repository or exists( join(self.repository.basedir, self.repository.METADIR)): return cmd = self.repository.command("co", "--quiet") if self.repository.ignore_externals: cmd.append("--ignore-externals") svnco = ExternalCommand(command=cmd) svnco.execute( "%s%s" % (self.repository.repository, self.repository.module), self.repository.basedir) ignore = [md for md in IGNORED_METADIRS] if self.logfile.startswith(self.repository.basedir): ignore.append(self.logfile[len(self.repository.basedir) + 1:]) if self.state_file.filename.startswith(self.repository.basedir): sfrelname = self.state_file.filename[len(self.repository.basedir) + 1:] ignore.append(sfrelname) ignore.append(sfrelname + '.old') ignore.append(sfrelname + '.journal') cmd = self.repository.command("propset", "%(propname)s", "--quiet") pset = ExternalCommand(cwd=self.repository.basedir, command=cmd) pset.execute('\n'.join(ignore), '.', propname='svn:ignore')
def _prepareWorkingDirectory(self, source_repo): """ Checkout a working copy of the target SVN repository. """ from os.path import join, exists from vcpx.dualwd import IGNORED_METADIRS if not self.repository.repository or exists(join(self.repository.basedir, self.repository.METADIR)): return cmd = self.repository.command("co", "--quiet") if self.repository.ignore_externals: cmd.append("--ignore-externals") svnco = ExternalCommand(command=cmd) svnco.execute("%s%s" % (self.repository.repository, self.repository.module), self.repository.basedir) ignore = [md for md in IGNORED_METADIRS] if self.logfile.startswith(self.repository.basedir): ignore.append(self.logfile[len(self.repository.basedir)+1:]) if self.state_file.filename.startswith(self.repository.basedir): sfrelname = self.state_file.filename[len(self.repository.basedir)+1:] ignore.append(sfrelname) ignore.append(sfrelname+'.old') ignore.append(sfrelname+'.journal') cmd = self.repository.command("propset", "%(propname)s", "--quiet") pset = ExternalCommand(cwd=self.repository.basedir, command=cmd) pset.execute('\n'.join(ignore), '.', propname='svn:ignore')
def _addPathnames(self, names): """ Add some new filesystem objects, skipping directories. In monotone *explicit* directory addition is always recursive, so adding a directory here might interfere with renames. Adding files without directories doesn't cause problems, because adding a file implicitly adds the parent directory (non-recursively). """ fnames = [] for fn in names: if isdir(join(self.repository.basedir, fn)): self.log.debug( "ignoring addition of directory %r " "(dirs are implicitly added by files)", fn) else: fnames.append(fn) if len(fnames): # ok, we still have something to add cmd = self.repository.command("add", "--") add = ExternalCommand(cwd=self.repository.basedir, command=cmd) add.execute(fnames, stdout=PIPE, stderr=PIPE) if add.exit_status: raise ChangesetApplicationFailure("%s returned status %s" % (str(add), add.exit_status))
def _prepareWorkingDirectory(self, source_repo): """ Possibly checkout a working copy of the target VC, that will host the upstream source tree, when overriden by subclasses. """ from re import escape if not self.repository.repository or exists(join(self.repository.basedir, '_MTN')): return if not self.repository.module: raise TargetInitializationFailure("Monotone needs a module " "defined (to be used as " "commit branch)") cmd = self.repository.command("setup", "--db", self.repository.repository, "--branch", self.repository.module) if self.repository.keygenid: self.repository.keyid = self.repository.keygenid if self.repository.keyid: cmd.extend( ("--key", self.repository.keyid) ) setup = ExternalCommand(command=cmd) setup.execute(self.repository.basedir, stdout=PIPE, stderr=PIPE) if self.repository.passphrase or self.repository.custom_lua: monotonerc = open(join(self.repository.basedir, '_MTN', 'monotonerc'), 'w') if self.repository.passphrase: monotonerc.write(MONOTONERC % self.repository.passphrase) else: raise TargetInitializationFailure("The passphrase must be specified") if self.repository.custom_lua: self.log.info("Adding custom lua script") monotonerc.write(self.repository.custom_lua) monotonerc.close() # Add the tailor log file and state file to _MTN's list of # ignored files ignored = [] logfile = self.repository.projectref().logfile if logfile.startswith(self.repository.basedir): ignored.append('^%s$' % escape(logfile[len(self.repository.basedir)+1:])) sfname = self.repository.projectref().state_file.filename if sfname.startswith(self.repository.basedir): sfrelname = sfname[len(self.repository.basedir)+1:] ignored.append('^%s$' % escape(sfrelname)) ignored.append('^%s$' % escape(sfrelname + '.old')) ignored.append('^%s$' % escape(sfrelname + '.journal')) if len(ignored) > 0: mt_ignored = open(join(self.repository.basedir, '.mtn-ignore'), 'a') mt_ignored.write('\n'.join(ignored)) mt_ignored.close()
def _renamePathname(self, oldname, newname): """ Rename a filesystem object. """ cmd = self.repository.command("copy") rename = ExternalCommand(cwd=self.repository.basedir, command=cmd) rename.execute(oldname, newname)
def _removePathnames(self, names): """ Remove some filesystem objects. """ cmd = self.repository.command("remove", "--quiet", "--force") remove = ExternalCommand(cwd=self.repository.basedir, command=cmd) remove.execute(names)
def _renamePathname(self, oldname, newname): """ Rename a filesystem object. """ cmd = self.repository.command("rename", "--") rename = ExternalCommand(cwd=self.repository.basedir, command=cmd) rename.execute(oldname, newname, stdout=PIPE, stderr=PIPE) if rename.exit_status: raise ChangesetApplicationFailure( "%s returned status %s" % (str(rename),rename.exit_status))
def _addSubtree(self, subdir): """ Add a whole subtree (recursively) """ cmd = self.repository.command("add", "--recursive", "--") add = ExternalCommand(cwd=self.repository.basedir, command=cmd) add.execute(subdir, stdout=PIPE, stderr=PIPE) if add.exit_status: raise ChangesetApplicationFailure("%s returned status %s" % (str(add),add.exit_status))
def _addSubtree(self, subdir): """ Add a whole subtree (recursively) """ cmd = self.repository.command("add", "--recursive", "--") add = ExternalCommand(cwd=self.repository.basedir, command=cmd) add.execute(subdir, stdout=PIPE, stderr=PIPE) if add.exit_status: raise ChangesetApplicationFailure("%s returned status %s" % (str(add), add.exit_status))
def _renamePathname(self, oldname, newname): """ Rename a filesystem object. """ cmd = self.repository.command("rename", "--") rename = ExternalCommand(cwd=self.repository.basedir, command=cmd) rename.execute(oldname, newname, stdout=PIPE, stderr=PIPE) if rename.exit_status: raise ChangesetApplicationFailure( "%s returned status %s" % (str(rename), rename.exit_status))
def testExitStatusForTrue(self): """Verify ExternalCommand exit_status of ``true``. """ if platform != 'win32': c = ExternalCommand(['true']) else: c = ExternalCommand(['cmd','/c exit 0']) c.execute() self.assertEqual(c.exit_status, 0)
def testExitStatusForFalse(self): """Verify ExternalCommand exit_status of ``false``. """ if platform != 'win32': c = ExternalCommand(['false']) else: c = ExternalCommand(['cmd','/c exit 1']) c.execute() self.assertNotEqual(c.exit_status, 0)
def testExitStatusForTrue(self): """Verify ExternalCommand exit_status of ``true``. """ if platform != 'win32': c = ExternalCommand(['true']) else: c = ExternalCommand(['cmd', '/c exit 0']) c.execute() self.assertEqual(c.exit_status, 0)
def testExitStatusForFalse(self): """Verify ExternalCommand exit_status of ``false``. """ if platform != 'win32': c = ExternalCommand(['false']) else: c = ExternalCommand(['cmd', '/c exit 1']) c.execute() self.assertNotEqual(c.exit_status, 0)
def _applyChangeset(self, changeset): cmd = self.repository.command("update", "--revision", changeset.revision) mtl = ExternalCommand(cwd=self.repository.basedir, command=cmd) mtl.execute(stdout=PIPE, stderr=PIPE) if mtl.exit_status: raise ChangesetApplicationFailure("'mtn update' returned " "status %s" % mtl.exit_status) mtr = MonotoneRevToCset(repository=self.repository, working_dir=self.repository.basedir, branch=self.repository.module) mtr.updateCset( changeset ) return False # no conflicts
def _handleConflict(self, changeset, conflicts, conflict): """ Handle the conflict raised by the application of the upstream changeset. Override parent behaviour: with darcs, we need to execute a revert on the conflicted files, **trashing** local changes, but there should be none of them in tailor context. """ self.log.info("Reverting changes to %s, to solve the conflict", ' '.join(conflict)) cmd = self.repository.command("revert", "--all") revert = ExternalCommand(cwd=self.repository.basedir, command=cmd) revert.execute(conflict)
def _removePathnames(self, names): """ Remove some filesystem object. """ from os.path import join, isdir # Currently git does not handle directories at all, so filter # them out. notdirs = [n for n in names if not isdir(join(self.repository.basedir, n))] if notdirs: cmd = self.repository.command("rm") c=ExternalCommand(cwd=self.repository.basedir, command=cmd) c.execute(notdirs)
def _prepareWorkingDirectory(self, source_repo): """ Checkout a working copy of the target CVS. """ from os.path import join, exists if not self.repository.repository or exists(join(self.repository.basedir, 'CVS')): return cmd = self.repository.command("-f", "-d", self.repository.repository, "co", "-d", self.repository.basedir) cvsco = ExternalCommand(command=cmd) cvsco.execute(self.repository.module)
def _applyChangeset(self, changeset): cmd = self.repository.command("update", "--revision", changeset.revision) mtl = ExternalCommand(cwd=self.repository.basedir, command=cmd) mtl.execute(stdout=PIPE, stderr=PIPE) if mtl.exit_status: raise ChangesetApplicationFailure("'mtn update' returned " "status %s" % mtl.exit_status) mtr = MonotoneRevToCset(repository=self.repository, working_dir=self.repository.basedir, branch=self.repository.module) mtr.updateCset(changeset) return False # no conflicts
def create(self): """ Create a new monotone DB, storing the commit keys, if available """ if not self.repository or exists(self.repository): return cmd = self.command("db", "init", "--db", self.repository) init = ExternalCommand(command=cmd) init.execute(stdout=PIPE, stderr=PIPE) if init.exit_status: raise TargetInitializationFailure("Was not able to initialize " "the monotone db at %r" % self.repository) if self.keyid: self.log.info("Using key %s for commits" % (self.keyid, )) else: # keystore key id unspecified, look at other options if self.keygenid: keyfile = join(getenv("HOME"), '.monotone', 'keys', self.keygenid) if exists(keyfile): self.log.info("Key %s exist, don't genkey again" % self.keygenid) else: # requested a new key cmd = self.command("genkey", "--db", self.repository) regkey = ExternalCommand(command=cmd) if self.passphrase: passp = "%s\n%s\n" % (self.passphrase, self.passphrase) else: passp = None regkey.execute(self.keygenid, input=passp, stdout=PIPE, stderr=PIPE) if regkey.exit_status: raise TargetInitializationFailure( "Was not able to setup " "the monotone initial key at %r" % self.repository) else: raise TargetInitializationFailure("Can't setup the monotone " "repository %r. " "A keyid or keygenid " "must be provided." % self.repository)
def _prepareWorkingDirectory(self, source_repo): """ Checkout a working copy of the target CVS. """ from os.path import join, exists if not self.repository.repository or exists( join(self.repository.basedir, 'CVS')): return cmd = self.repository.command("-f", "-d", self.repository.repository, "co", "-d", self.repository.basedir) cvsco = ExternalCommand(command=cmd) cvsco.execute(self.repository.module)
def testStandardOutput(self): """Verify that ExternalCommand redirects stdout.""" if platform != 'win32': c = ExternalCommand(['echo']) else: c = ExternalCommand(['cmd','/c','echo']) out = c.execute("ciao", stdout=PIPE)[0] self.assertEqual(out.read(), "ciao\n") if platform != 'win32': out = c.execute('-n', stdout=PIPE)[0] self.assertEqual(out.read(), '') out = c.execute("ciao")[0] self.assertEqual(out, None)
def _getUpstreamChangesets(self, sincerev=None): from os.path import join, exists branch="HEAD" fname = join(self.repository.basedir, 'CVS', 'Tag') if exists(fname): tag = open(fname).read() if tag.startswith('T'): branch=tag[1:-1] else: if sincerev is not None and isinstance(sincerev, basestring) \ and not sincerev[0] in '0123456789': branch = sincerev sincerev = None if sincerev: sincerev = int(sincerev) cmd = self.repository.command("--norc", "--cvs-direct", "-u", "-b", branch, "--root", self.repository.repository, cvsps=True) cvsps = ExternalCommand(command=cmd) log = cvsps.execute(self.repository.module, stdout=PIPE, TZ='UTC0')[0] for cs in changesets_from_cvsps(log, sincerev): yield cs
def __parse_revision_logs(self, fqrevlist, update=True): changesets = [] logparser = Parser() c = ExternalCommand(cwd=self.repository.basedir, command=self.repository.command("cat-archive-log")) for fqrev in fqrevlist: out, err = c.execute(fqrev, stdout=PIPE, stderr=PIPE) if c.exit_status: raise GetUpstreamChangesetsFailure( "%s returned status %d saying\n%s" % (str(c), c.exit_status, err.read())) err = None try: msg = logparser.parse(out) except Exception, err: pass if not err and msg.is_multipart(): err = "unable to parse log description" if not err and update and msg.has_key('Continuation-of'): err = "in-version continuations not supported" if err: raise GetUpstreamChangesetsFailure(str(err)) date = self.__parse_date(msg['Date'], msg['Standard-date']) author = msg['Creator'] revision = fqrev logmsg = [msg['Summary']] s = msg.get('Keywords', "").strip() if s: logmsg.append('Keywords: ' + s) s = msg.get_payload().strip() if s: logmsg.append(s) logmsg = '\n'.join(logmsg) changesets.append(Changeset(revision, date, author, logmsg))
def _getUpstreamChangesets(self, sincerev=None): from os.path import join, exists branch = "HEAD" fname = join(self.repository.basedir, 'CVS', 'Tag') if exists(fname): tag = open(fname).read() if tag.startswith('T'): branch = tag[1:-1] else: if sincerev is not None and isinstance(sincerev, basestring) \ and not sincerev[0] in '0123456789': branch = sincerev sincerev = None if sincerev: sincerev = int(sincerev) cmd = self.repository.command("--norc", "--cvs-direct", "-u", "-b", branch, "--root", self.repository.repository, cvsps=True) cvsps = ExternalCommand(command=cmd) log = cvsps.execute(self.repository.module, stdout=PIPE, TZ='UTC0')[0] for cs in changesets_from_cvsps(log, sincerev): yield cs
def darcs_version(self): if self._darcs_version is None: cmd = self.command('--version') version = ExternalCommand(command=cmd) self._darcs_version = version.execute(stdout=PIPE)[0].read().strip() self.log.debug('Using %s, version %s', self.EXECUTABLE, self._darcs_version) return self._darcs_version
def _getUpstreamChangesets(self, sincerev=None): if sincerev: sincerev = int(sincerev) else: sincerev = 0 cmd = self.repository.command("log", "--verbose", "--xml", "--non-interactive", "--revision", "%d:HEAD" % (sincerev + 1)) svnlog = ExternalCommand(cwd=self.repository.basedir, command=cmd) log = svnlog.execute('.', stdout=PIPE, TZ='UTC0')[0] if svnlog.exit_status: return [] if self.repository.filter_badchars: from string import maketrans from cStringIO import StringIO # Apparently some (SVN repo contains)/(SVN server dumps) some # characters that are illegal in an XML stream. This was the case # with Twisted Matrix master repository. To be safe, we replace # all of them with a question mark. if isinstance(self.repository.filter_badchars, basestring): allbadchars = self.repository.filter_badchars else: allbadchars = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" \ "\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15" \ "\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7f" tt = maketrans(allbadchars, "?" * len(allbadchars)) log = StringIO(log.read().translate(tt)) return changesets_from_svnlog(log, self.repository)
def _getUpstreamChangesets(self, sincerev=None): if sincerev: sincerev = int(sincerev) else: sincerev = 0 cmd = self.repository.command("log", "--verbose", "--xml", "--non-interactive", "--revision", "%d:HEAD" % (sincerev+1)) svnlog = ExternalCommand(cwd=self.repository.basedir, command=cmd) log = svnlog.execute('.', stdout=PIPE, TZ='UTC0')[0] if svnlog.exit_status: return [] if self.repository.filter_badchars: from string import maketrans from cStringIO import StringIO # Apparently some (SVN repo contains)/(SVN server dumps) some # characters that are illegal in an XML stream. This was the case # with Twisted Matrix master repository. To be safe, we replace # all of them with a question mark. if isinstance(self.repository.filter_badchars, basestring): allbadchars = self.repository.filter_badchars else: allbadchars = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" \ "\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15" \ "\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7f" tt = maketrans(allbadchars, "?"*len(allbadchars)) log = StringIO(log.read().translate(tt)) return changesets_from_svnlog(log, self.repository)
def __move_file(self, old_name, new_name): # # The aegis command to rename files does not have the -keep # option to preserve the content of the file, do it manually. # fp = open(os.path.join(self.repository.basedir, new_name), 'rb') content = fp.read() fp.close() cmd = self.repository.command("-move", "-not-logging", "-project", self.repository.module, "-change", self.change_number) move_file = ExternalCommand(cwd=self.repository.basedir, command=cmd) output = move_file.execute(old_name, new_name, stdout=PIPE, stderr=STDOUT)[0] if move_file.exit_status > 0: raise ChangesetApplicationFailure( "%s returned status %d, saying: %s" % (str(move_file), move_file.exit_status, output.read())) # # Restore the previously saved content of the renamed file. # fp = open(os.path.join(self.repository.basedir, new_name), 'wb') fp.write(content) fp.close()
def _commit(self, date, author, patchname, changelog=None, entries=None, tags=[], isinitialcommit=False): """ Commit the changeset. """ encode = self.repository.encode logmessage = [] if patchname: logmessage.append(patchname) if changelog: logmessage.append(changelog) # If we cannot use propset, fall back to old behaviour of # appending these info to the changelog if not self.repository.use_propset: logmessage.append('') logmessage.append('Original author: %s' % encode(author)) logmessage.append('Date: %s' % date) elif not self.repository.propset_date: logmessage.append('') logmessage.append('Date: %s' % date) rontf = ReopenableNamedTemporaryFile('svn', 'tailor') log = open(rontf.name, "w") log.write(encode('\n'.join(logmessage))) log.close() cmd = self.repository.command("commit", "--file", rontf.name) commit = ExternalCommand(cwd=self.repository.basedir, command=cmd) if not entries or self.repository.commit_all_files: entries = ['.'] out, err = commit.execute(entries, stdout=PIPE, stderr=PIPE) if commit.exit_status: raise ChangesetApplicationFailure( "%s returned status %d saying\n%s" % (str(commit), commit.exit_status, err.read())) revision = self._propsetRevision(out, commit, date, author) if not revision: # svn did not find anything to commit return cmd = self.repository.command("update", "--quiet") if self.repository.ignore_externals: cmd.append("--ignore-externals") cmd.extend(["--revision", revision]) ExternalCommand(cwd=self.repository.basedir, command=cmd).execute()
def testStandardOutput(self): """Verify that ExternalCommand redirects stdout.""" if platform != 'win32': c = ExternalCommand(['echo']) else: c = ExternalCommand(['cmd', '/c', 'echo']) out = c.execute("ciao", stdout=PIPE)[0] self.assertEqual(out.read(), "ciao\n") if platform != 'win32': out = c.execute('-n', stdout=PIPE)[0] self.assertEqual(out.read(), '') out = c.execute("ciao")[0] self.assertEqual(out, None)
def _removePathnames(self, names): """ Remove some filesystem object. """ from os.path import join, isdir # Currently git does not handle directories at all, so filter # them out. notdirs = [ n for n in names if not isdir(join(self.repository.basedir, n)) ] if notdirs: cmd = self.repository.command("rm") c = ExternalCommand(cwd=self.repository.basedir, command=cmd) c.execute(notdirs)
def __move_file(self, old_name, new_name): # # The aegis command to rename files does not have the -keep # option to preserve the content of the file, do it manually. # fp = open(os.path.join(self.repository.basedir, new_name), 'rb') content = fp.read() fp.close() cmd = self.repository.command("-move", "-not-logging", "-project", self.repository.module, "-change", self.change_number) move_file = ExternalCommand(cwd=self.repository.basedir, command=cmd) output = move_file.execute(old_name, new_name, stdout = PIPE, stderr = STDOUT)[0] if move_file.exit_status > 0: raise ChangesetApplicationFailure( "%s returned status %d, saying: %s" % (str(move_file), move_file.exit_status, output.read())) # # Restore the previously saved content of the renamed file. # fp = open(os.path.join(self.repository.basedir, new_name), 'wb') fp.write(content) fp.close()
def _prepareWorkingDirectory(self, source_repo): """ Checkout a working copy of the target CVS. """ from os.path import join, exists, split if not self.repository.repository or exists(join(self.repository.basedir, 'CVS')): return # CVS does not handle "checkout -d multi/level/subdir", so # split the basedir and use it's parentdir as cwd below. parentdir, subdir = split(self.repository.basedir) cmd = self.repository.command("-f", "-d", self.repository.repository, "co", "-d", subdir) cvsco = ExternalCommand(cwd=parentdir, command=cmd) cvsco.execute(self.repository.module)
def create(self): """ Execute ``cg init``. """ from os.path import join, exists if exists(join(self.basedir, self.METADIR)): return cmd = self.command("init", "-I") init = ExternalCommand(cwd=self.basedir, command=cmd) init.execute() if init.exit_status: raise TargetInitializationFailure("%s returned status %s" % (str(init), init.exit_status))
def _prepareWorkingDirectory(self, source_repo): """ Checkout a working copy of the target SVN repository. """ from os.path import join, exists if not self.repository.repository or exists(join(self.repository.basedir, self.repository.METADIR)): return cmd = self.repository.command("co", "--quiet") if self.repository.ignore_externals: cmd.append("--ignore-externals") svnco = ExternalCommand(command=cmd) svnco.execute("%s%s" % (self.repository.repository, self.repository.module), self.repository.basedir)
def testSplittedExecution(self): """Verify the mechanism that avoids too long command lines""" args = [str(i) * 20 for i in range(10)] if platform != 'win32': c = ExternalCommand(['echo']) else: c = ExternalCommand(['cmd','/c','echo']) c.MAX_CMDLINE_LENGTH = 30 out = c.execute(args, stdout=PIPE)[0] self.assertEqual(out.read(), '\n'.join([args[i]+' '+args[i+1] for i in range(0,10,2)])+'\n') c = ExternalCommand(['echo']) c.MAX_CMDLINE_LENGTH = None out = c.execute(args, stdout=PIPE)[0] self.assertEqual(out.read(), ' '.join(args)+'\n')
def create(self): """ Execute ``cg init``. """ from os.path import join, exists if exists(join(self.basedir, self.METADIR)): return cmd = self.command("init", "-I") init = ExternalCommand(cwd=self.basedir, command=cmd) init.execute() if init.exit_status: raise TargetInitializationFailure( "%s returned status %s" % (str(init), init.exit_status))
def _removePathnames(self, names): """ Remove some filesystem object. """ from os.path import join, exists # darcs raises status 512 when it does not find the entry, # removed by source. Since sometime a directory is left there # because it's not empty, darcs fails. So, do an explicit # remove on items that are still there. c = ExternalCommand(cwd=self.repository.basedir, command=self.repository.command("remove")) existing = [n for n in names if exists(join(self.repository.basedir, n))] if existing: c.execute(existing)
def create(self): """ Create the base directory if it doesn't exist, and the repository as well in the new working directory, executing a ``cdv init`` there. """ from os.path import join, normpath, exists if exists(join(self.basedir, self.METADIR)): return init = ExternalCommand(cwd=self.basedir, command=self.command("init")) init.execute() if init.exit_status: raise TargetInitializationFailure( "%s returned status %s" % (str(init), init.exit_status))
def darcs_version(self): if self._darcs_version is None: cmd = self.command('--version') version = ExternalCommand(command=cmd) self._darcs_version = version.execute( stdout=PIPE)[0].read().strip() self.log.debug('Using %s, version %s', self.EXECUTABLE, self._darcs_version) return self._darcs_version
def __delta_name(self, delta): cmd = self.repository.command("-delta_name", "-project", self.repository.module) delta_name = ExternalCommand(cwd="/tmp", command=cmd) output = delta_name.execute(delta, stdout=PIPE, stderr=STDOUT)[0] if delta_name.exit_status > 0: raise ChangesetApplicationFailure( "%s returned status %d, saying: %s" % (str(delta_name), delta_name.exit_status, output.read()))
def __apply_changeset(self, changeset): c = ExternalCommand(cwd=self.repository.basedir, command=self.repository.command("update")) out, err = c.execute(changeset.revision, stdout=PIPE, stderr=PIPE) if not c.exit_status in [0, 1]: raise ChangesetApplicationFailure( "%s returned status %d saying\n%s" % (str(c), c.exit_status, err.read())) return self.__parse_apply_changeset_output(changeset, out)