These patches supersede the ones I sent out a few minutes ago from
quilt. They are from the darcs tip and I just caught a brown paper bag
bug in revision ID parsing introduced at the last second. I had
intended to support the hex IDs, but inadvertently broke the other
kind. Now everything should work again.. I'm running it against my
mutt tree originally tailorized from CVS right now :)
New patches:
[Ensure str() doesn't get handed a unicode changeset
Brendan Cully <[EMAIL PROTECTED]>**20051114021851
I don't do a lot of python, so I may be misdiagnosing this bug, but I
get a UnicodeEncodeError at Tailorizer.applyable on the debug line
when tailorizing a source with non-ascii log messages on a UTF-8
terminal. It appears that str() expects a __str__ function it calls to
return a plain (not unicode) string. Could possibly be an OS X issue.
The particular test was tailorizing the bzr repository from bzr to git
or hglib, with changeset messages apparently in macroman, on a UTF-8
terminal. This problem is made more annoying by the fact that bzr no
longer seems to be able to resume (_b undefined in the upgrade path).
] {
hunk ./vcpx/changes.py 145
+ import codecs
+
hunk ./vcpx/changes.py 161
- return '\n'.join(s)
+ s = '\n'.join(s)
+ if isinstance(s, unicode):
+ s = s.encode('ascii', 'replace')
+ return s
}
[git commit fixes (date, # at end of commit message)
Brendan Cully <[EMAIL PROTECTED]>**20051114022122
As of at least git 0.99.9e, git refuses to parse timestamps with
microseconds such as str(datetime) may emit. This patch uses strftime
to force the format to something simpler.
It also manually duplicates GIT_AUTHOR_* to GIT_COMMITTER_* so that
cg-log produces output most similar to the source log.
git-commit expects the commit message to end with a newline, so this
patch adds one if it isn't already there.
] {
hunk ./vcpx/git.py 76
+ env['GIT_COMMITTER_NAME']=name
hunk ./vcpx/git.py 79
+ env['GIT_COMMITTER_EMAIL']=email
hunk ./vcpx/git.py 81
- env['GIT_AUTHOR_DATE']=str(date)
+ env['GIT_AUTHOR_DATE']=date.strftime("%Y-%m-%d %H:%M:%S")
+ env['GIT_COMMITTER_DATE']=env['GIT_AUTHOR_DATE']
hunk ./vcpx/git.py 88
- (out, _) = c.execute(stdout=PIPE, env=env, input='\n'.join(logmessage))
+ logmessage = '\n'.join(logmessage)
+ if not logmessage.endswith('\n'):
+ logmessage += '\n'
+ (out, _) = c.execute(stdout=PIPE, env=env, input=logmessage)
}
[Mercurial source support via hglib
Brendan Cully <[EMAIL PROTECTED]>**20051114022602] {
hunk ./README 45
-.. [#] ArX, Codeville, Git and Mercurial systems may be
- used only as the `target` backend, since the `source` support
- isn't coded yet. Contributions on these backends will be very
- appreciated, since I do not use them enough to figure out the
- best way to get pending changes and build tailor ChangeSets out
- of them.
+.. [#] ArX, Codeville and Git systems may be used only as the `target`
+ backend, since the `source` support isn't coded yet.
+ Contributions on these backends will be very appreciated,
+ since I do not use them enough to figure out the best way to
+ get pending changes and build tailor ChangeSets out of them.
hunk ./README 269
-c) ArX, Baazar-NG, Codeville, Git, and Mercurial are (currently) only
+c) ArX, Baazar-NG, Codeville and Git are (currently) only
hunk ./vcpx/hglib.py 5
+# Brendan Cully <[EMAIL PROTECTED]>
hunk ./vcpx/hglib.py 16
+from source import UpdatableSourceWorkingDir
hunk ./vcpx/hglib.py 19
+import os, pdb
hunk ./vcpx/hglib.py 21
-class HglibWorkingDir(SyncronizableTargetWorkingDir):
+class HglibWorkingDir(UpdatableSourceWorkingDir,
SyncronizableTargetWorkingDir):
+ # UpdatableSourceWorkingDir
+ def _checkoutUpstreamRevision(self, revision):
+ """
+ Initial checkout (hg clone)
+ """
+
+ self._getUI()
+ # We have to clone the entire repository to be able to pull from it
+ # later. So a partial checkout is a full clone followed by an update
+ # directly to the desired revision.
+
+ # Hg won't check out into an existing directory
+ checkoutdir = os.path.join(self.basedir,".hgtmp")
+ commands.clone(self._ui, self.repository.repository, checkoutdir,
+ noupdate=True, ssh=None, remotecmd=None)
+ os.rename(os.path.join(checkoutdir, ".hg"),
+ os.path.join(self.basedir,".hg"))
+ os.rmdir(checkoutdir)
+
+ repo = self._getRepo()
+ node = self._getNode(repo, revision)
+
+ self.log.info('Extracting revision %s from %s into %s',
+ revision, self.repository.repository, self.basedir)
+ repo.update(node)
+
+ return self._changesetForRevision(repo, revision)
+
+ def _getUpstreamChangesets(self, sincerev):
+ """Fetch new changesets from the source"""
+ ui = self._getUI()
+ repo = self._getRepo()
+
+ commands.pull(ui, repo, "default", ssh=None, remotecmd=None,
update=None)
+
+ from mercurial.node import bin
+ for rev in xrange(repo.changelog.rev(bin(sincerev)) + 1,
repo.changelog.count()):
+ yield self._changesetForRevision(repo, str(rev))
+
+ def _applyChangeset(self, changeset):
+ repo = self._getRepo()
+ node = self._getNode(repo, changeset.revision)
+
+ return repo.update(node)
+
+ def _changesetForRevision(self, repo, revision):
+ from changes import Changeset, ChangesetEntry
+ from datetime import datetime
+
+ entries = []
+ node = self._getNode(repo, revision)
+ (manifest, user, date, files, message) = repo.changelog.read(node)
+ manifest = repo.manifest.read(manifest)
+
+ # To find adds, we get the manifests of any parents. If a file doesn't
+ # occur there, it's new.
+ pms = {}
+ for parent in repo.changelog.parents(node):
+ pms.update(repo.manifest.read(repo.changelog.read(parent)[0]))
+
+ # Different targets seem to handle the TZ differently. It looks like
+ # darcs may be the most correct.
+ (dt, tz) = date.split(' ')
+ date = datetime.fromtimestamp(int(dt) + int(tz))
+
+ # Every time we find a file in the current manifest, we pop it from
the parents.
+ # Anything left over in parents is a deleted file.
+ for f in files:
+ e = ChangesetEntry(f)
+ # find renames
+ fl = repo.file(f)
+ oldname = fl.renamed(manifest[f])
+ if oldname:
+ e.action_kind = ChangesetEntry.RENAMED
+ e.old_name = oldname[0]
+ pms.pop(oldname[0])
+ else:
+ try:
+ del pms[f]
+ e.action_kind = ChangesetEntry.UPDATED
+ except KeyError:
+ e.action_kind = ChangesetEntry.ADDED
+
+ entries.append(e)
+
+ for df in pms.iterkeys():
+ e = ChangesetEntry(df)
+ e.action_kind = ChangesetEntry.DELETED
+
+ from mercurial.node import hex
+ revision = hex(repo.changelog.lookup(revision))
+ return Changeset(revision, date, user, message, entries)
+
+ def _getUI(self):
+ try:
+ return self._ui
+ except AttributeError:
+ project = self.repository.projectref()
+ self._ui = ui.ui(project.verbose,
+ project.config.get(self.repository.name,
+ 'debug', False),
+ not project.verbose, False)
+ return self._ui
+
+ def _getRepo(self):
+ try:
+ return self._hg
+ except AttributeError:
+ ui = self._getUI()
+ self._hg = hg.repository(ui=ui, path=self.basedir, create=False)
+ return self._hg
+
+ def _getNode(self, repo, revision):
+ """Convert a tailor revision ID into an hg node"""
+ if revision == "HEAD":
+ node = repo.changelog.tip()
+ else:
+ if revision == "INITIAL":
+ rev = "0"
+ else:
+ rev = revision
+ node = repo.changelog.lookup(rev)
+
+ return node
hunk ./vcpx/hglib.py 221
- project = self.repository.projectref()
- self._ui = ui.ui(project.verbose,
- project.config.get(self.repository.name,
- 'debug', False),
- project.verbose, False)
+ self._getUI()
}
[Fix a last-second BPB converting revision names.
Brendan Cully <[EMAIL PROTECTED]>**20051114030337] {
hunk ./vcpx/hglib.py 19
-import os, pdb
+import os
hunk ./vcpx/hglib.py 112
- revision = hex(repo.changelog.lookup(revision))
+ revision = hex(node)
}
Context:
[Ignore the backup copy of the state file
[EMAIL PROTECTED]
[Fix cut&paste error
[EMAIL PROTECTED]
[TAG Version 0.9.19 (retag)
[EMAIL PROTECTED]
Patch bundle hash:
d025aaab13f294cd7f15b41a8a567ac3ad653022
_______________________________________________
Tailor mailing list
[email protected]
http://lists.zooko.com/mailman/listinfo/tailor