[PATCH] convert: keep track of files created in filtered-out revisions
Yury Sulsky
yury.sulsky at gmail.com
Sun Nov 27 07:51:14 CST 2011
This patch makes the semantics of --includerevs and --excluderevs much
nicer. Previously, if you created (or deleted) a file in a skipped
revision and didn't modify it subsequently, the file would not exist
(or still exist) in the destination repo. Now we just keep track of
these files when using --includerevs or --excluderevs.
Yury
On Sun, Nov 27, 2011 at 8:41 AM, Yury Sulsky <yury.sulsky at gmail.com> wrote:
> # HG changeset patch
> # User Yury Sulsky <yury.sulsky at gmail.com>
> # Date 1322370781 18000
> # Branch stable
> # Node ID e86bc97a0a38b9497342b69a0eda9cce3b1c5d58
> # Parent 2d5e44d732e5207a683300f12207ef147b0e4e67
> convert: keep track of files created in filtered-out revisions
>
> diff -r 2d5e44d732e5 -r e86bc97a0a38 hgext/convert/filtermap.py
> --- a/hgext/convert/filtermap.py Sat Nov 26 15:51:10 2011 -0500
> +++ b/hgext/convert/filtermap.py Sun Nov 27 00:13:01 2011 -0500
> @@ -23,7 +23,7 @@
> """Return True if we want to keep this revision"""
> return True
>
> - def __init__(self, ui, baseconverter):
> + def __init__(self, ui, baseconverter, trackchanges):
> super(filtermap_base, self).__init__(ui)
> self.base = baseconverter
> self.commits = {}
> @@ -38,6 +38,8 @@
> self.origparents = {}
> self.children = {}
> self.seenchildren = {}
> + self.skippedchanges = {}
> + self.trackingchanges = trackchanges
>
> def before(self):
> self.base.before()
> @@ -51,7 +53,7 @@
> # To avoid calling getcommit for every revision that has already
> # been converted, we rebuild only the parentmap, delaying the
> # rebuild of wantedancestors until we need it (i.e. until a
> - # merge).
> + # merge or if we are tracking changes).
> #
> # We assume the order argument lists the revisions in
> # topological order, so that we can infer which revisions were
> @@ -83,6 +85,7 @@
> self.parentmap.clear()
> self.wantedancestors.clear()
> self.seenchildren.clear()
> + self.skippedchanges.clear()
> for rev, wanted, arg in self.convertedorder:
> if rev not in self.origparents:
> self.origparents[rev] = self.getcommit(rev).parents
> @@ -124,12 +127,41 @@
> del self.wantedancestors[r]
> del self.parentmap[r]
> del self.seenchildren[r]
> + if self.trackingchanges:
> + del self.skippedchanges[r]
> if self._rebuilt:
> del self.children[r]
>
> + def _trackedchanges(self, rev, parents):
> + changes = self.base.getchanges(rev)
> + if not self.trackingchanges or not parents:
> + return changes
> +
> + files, copies = set(), {}
> + # The case of a convergent copy takes care of itself because
> + # the destination file should be present in the merge node's
> + # list of changed files
> + for p in parents:
> + pf, pc = self.skippedchanges[p]
> + copies.update(pc)
> + files.update([(f, rev) for (f, prev) in pf])
> +
> + cf, cc = changes
> + copies.update(cc); files.update(cf)
> +
> + for dest in copies:
> + if dest in files:
> + del copies[dest]
> +
> + return files, copies
> +
> +
> def mark_not_wanted(self, rev, p):
> # Mark rev as not interesting and update data structures.
>
> + if self.trackingchanges:
> + self.skippedchanges[rev] = self._trackedchanges(rev, p and [p])
> +
> if p is None:
> # A root revision. Use SKIPREV to indicate that it doesn't
> # map to any revision in the restricted graph. Put SKIPREV
> @@ -145,6 +177,9 @@
> def mark_wanted(self, rev, parents):
> # Mark rev ss wanted and update data structures.
>
> + if self.trackingchanges:
> + self.skippedchanges[rev] = [], {}
> +
> # rev will be in the restricted graph, so children of rev in
> # the original graph should still have rev as a parent in the
> # restricted graph.
> @@ -158,9 +193,10 @@
> wrev.add(rev)
> self.wantedancestors[rev] = wrev
>
> +
> def getchanges(self, rev):
> parents = self.commits[rev].parents
> - if len(parents) > 1:
> + if len(parents) > 1 or self.trackingchanges:
> self.rebuild()
>
> # To decide whether we're interested in rev we:
> @@ -197,6 +233,7 @@
> self.origparents[rev] = parents
>
> closed = False
> +
> if 'close' in self.commits[rev].extra:
> # A branch closing revision is only useful if one of its
> # parents belong to the branch being closed
> @@ -221,9 +258,18 @@
> # Rewrite the parents of the commit object
> self.commits[rev].parents = mparents
> self.mark_wanted(rev, parents)
> +
> + changes = self._trackedchanges(rev, parents)
> + self._discard(*parents)
> self.convertedorder.append((rev, True, None))
> - self._discard(*parents)
> - return self.base.getchanges(rev)
> +
> + if not mparents:
> + # If this is a root node, flatten copies.
> + files, copies = changes
> + files = set(files)
> + files.update([(dest, rev) for dest in copies.keys()])
> + changes = files, {}
> + return changes
>
> def getfile(self, name, rev):
> return self.base.getfile(name, rev)
> @@ -256,7 +302,11 @@
>
> class filtermap_source(filtermap_base):
> def __init__(self, ui, base, inrevs = None, outrevs = None, filemap = None):
> - super(filtermap_source, self).__init__(ui, base)
> + # If we filter by revisions (not by files), we need to track
> + # files that have been created or copied in the revisions we've
> + # filtered out.
> + trackchanges = inrevs is not None or outrevs is not None
> + super(filtermap_source, self).__init__(ui, base, trackchanges)
> if inrevs:
> self.inrevs = self.parserevset(inrevs)
> else:
> diff -r 2d5e44d732e5 -r e86bc97a0a38 tests/test-convert-pickrevs.t
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/tests/test-convert-pickrevs.t Sun Nov 27 00:13:01 2011 -0500
> @@ -0,0 +1,207 @@
> +
> + $ HGMERGE=true; export HGMERGE
> + $ echo '[extensions]' >> $HGRCPATH
> + $ echo 'graphlog =' >> $HGRCPATH
> + $ echo 'convert =' >> $HGRCPATH
> + $ glog()
> + > {
> + > hg glog --template '{rev} "{desc}" files: {files}\n' "$@"
> + > }
> + $ hg init source
> + $ cd source
> + $ echo foo > foo
> + $ echo baz > baz
> + $ mkdir -p dir/subdir
> + $ echo dir/file >> dir/file
> + $ echo dir/file2 >> dir/file2
> + $ echo dir/file3 >> dir/file3 # to be corrupted in rev 0
> + $ echo dir/subdir/file3 >> dir/subdir/file3
> + $ echo dir/subdir/file4 >> dir/subdir/file4
> + $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
> + $ echo bar > bar
> + $ echo quux > quux
> + $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
> + $ hg copy foo copied
> + $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
> + $ echo >> foo
> + $ hg ci -d '2 0' -m '2: change foo'
> + $ hg up -qC 1
> + $ echo >> bar
> + $ echo >> quux
> + $ hg ci -d '3 0' -m '3: change bar quux'
> + created new head
> + $ hg up -qC 2
> + $ hg merge -qr 3
> + $ echo >> bar
> + $ echo >> baz
> + $ hg ci -d '4 0' -m '4: first merge; change bar baz'
> + $ echo >> bar
> + $ echo 1 >> baz
> + $ echo >> quux
> + $ hg ci -d '5 0' -m '5: change bar baz quux'
> + $ hg up -qC 4
> + $ echo >> foo
> + $ echo 2 >> baz
> + $ hg ci -d '6 0' -m '6: change foo baz'
> + created new head
> + $ hg up -qC 5
> + $ hg merge -qr 6
> + $ echo >> bar
> + $ hg ci -d '7 0' -m '7: second merge; change bar'
> + $ echo >> foo
> + $ hg ci -m '8: change foo'
> + $ glog
> + @ 8 "8: change foo" files: foo
> + |
> + o 7 "7: second merge; change bar" files: bar baz
> + |\
> + | o 6 "6: change foo baz" files: baz foo
> + | |
> + o | 5 "5: change bar baz quux" files: bar baz quux
> + |/
> + o 4 "4: first merge; change bar baz" files: bar baz
> + |\
> + | o 3 "3: change bar quux" files: bar quux
> + | |
> + o | 2 "2: change foo" files: foo
> + |/
> + o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
> + |
> + o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
> +
> + $ cd ..
> + $ cat >>include.revs <<EOF
> + > 1
> + > 6
> + > 8
> + > EOF
> + $ hg convert --includerevs include.revs source dest1
> + initializing destination dest1 repository
> + scanning source...
> + sorting...
> + converting...
> + 8 0: add foo baz dir/
> + 7 1: add bar quux; copy foo to copied
> + 6 2: change foo
> + 5 3: change bar quux
> + 4 4: first merge; change bar baz
> + 3 5: change bar baz quux
> + 2 6: change foo baz
> + 1 7: second merge; change bar
> + 0 8: change foo
> + $ hg glog -R dest1 --debug
> + o changeset: 2:aae4e6787d5247344e528cf6683402253c5f81d3
> + | tag: tip
> + | parent: 1:15e417a5c00afbafbf451ac3b909e9b09a5d6c37
> + | parent: -1:0000000000000000000000000000000000000000
> + | manifest: 2:3bd158bd8138cde9385fde4ed930f3376bf5881e
> + | user: test
> + | date: Thu Jan 01 00:00:00 1970 +0000
> + | files: bar baz foo
> + | extra: branch=default
> + | description:
> + | 8: change foo
> + |
> + |
> + o changeset: 1:15e417a5c00afbafbf451ac3b909e9b09a5d6c37
> + | parent: 0:505780bbef8a0939a7ebb81b3972241566f73e81
> + | parent: -1:0000000000000000000000000000000000000000
> + | manifest: 1:4e1b63e06f1509fa11224e55f7e3b311d9549c95
> + | user: test
> + | date: Thu Jan 01 00:00:06 1970 +0000
> + | files: bar baz foo quux
> + | extra: branch=default
> + | description:
> + | 6: change foo baz
> + |
> + |
> + o changeset: 0:505780bbef8a0939a7ebb81b3972241566f73e81
> + parent: -1:0000000000000000000000000000000000000000
> + parent: -1:0000000000000000000000000000000000000000
> + manifest: 0:32cf238e6cc88a093c3d1d6e0f1ccab71423e3a1
> + user: test
> + date: Thu Jan 01 00:00:01 1970 +0000
> + files+: bar baz copied dir/file dir/file2 dir/file3 dir/file4 dir/subdir/file3 dir/subdir/file4 foo quux
> + extra: branch=default
> + description:
> + 1: add bar quux; copy foo to copied
> +
> +
> + $ hg up -R dest1; ls dest1
> + 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
> + bar
> + baz
> + copied
> + dir
> + foo
> + quux
> +
> + $ cat >>exclude.revs <<EOF
> + > 0
> + > 2
> + > 3
> + > 4
> + > 5
> + > 7
> + > EOF
> + $ hg convert --excluderevs exclude.revs source dest2
> + initializing destination dest2 repository
> + scanning source...
> + sorting...
> + converting...
> + 8 0: add foo baz dir/
> + 7 1: add bar quux; copy foo to copied
> + 6 2: change foo
> + 5 3: change bar quux
> + 4 4: first merge; change bar baz
> + 3 5: change bar baz quux
> + 2 6: change foo baz
> + 1 7: second merge; change bar
> + 0 8: change foo
> + $ hg glog -R dest1 --debug
> + @ changeset: 2:aae4e6787d5247344e528cf6683402253c5f81d3
> + | tag: tip
> + | parent: 1:15e417a5c00afbafbf451ac3b909e9b09a5d6c37
> + | parent: -1:0000000000000000000000000000000000000000
> + | manifest: 2:3bd158bd8138cde9385fde4ed930f3376bf5881e
> + | user: test
> + | date: Thu Jan 01 00:00:00 1970 +0000
> + | files: bar baz foo
> + | extra: branch=default
> + | description:
> + | 8: change foo
> + |
> + |
> + o changeset: 1:15e417a5c00afbafbf451ac3b909e9b09a5d6c37
> + | parent: 0:505780bbef8a0939a7ebb81b3972241566f73e81
> + | parent: -1:0000000000000000000000000000000000000000
> + | manifest: 1:4e1b63e06f1509fa11224e55f7e3b311d9549c95
> + | user: test
> + | date: Thu Jan 01 00:00:06 1970 +0000
> + | files: bar baz foo quux
> + | extra: branch=default
> + | description:
> + | 6: change foo baz
> + |
> + |
> + o changeset: 0:505780bbef8a0939a7ebb81b3972241566f73e81
> + parent: -1:0000000000000000000000000000000000000000
> + parent: -1:0000000000000000000000000000000000000000
> + manifest: 0:32cf238e6cc88a093c3d1d6e0f1ccab71423e3a1
> + user: test
> + date: Thu Jan 01 00:00:01 1970 +0000
> + files+: bar baz copied dir/file dir/file2 dir/file3 dir/file4 dir/subdir/file3 dir/subdir/file4 foo quux
> + extra: branch=default
> + description:
> + 1: add bar quux; copy foo to copied
> +
> +
> + $ hg up -R dest2; ls dest2
> + 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
> + bar
> + baz
> + copied
> + dir
> + foo
> + quux
> +
>
More information about the Mercurial-devel
mailing list