Show More
@@ -185,6 +185,8 b' class svn_source(converter_source):' | |||||
185 | self.ra = self.transport.ra |
|
185 | self.ra = self.transport.ra | |
186 | self.ctx = self.transport.client |
|
186 | self.ctx = self.transport.client | |
187 | self.base = svn.ra.get_repos_root(self.ra) |
|
187 | self.base = svn.ra.get_repos_root(self.ra) | |
|
188 | # Module is either empty or a repository path starting with | |||
|
189 | # a slash and not ending with a slash. | |||
188 | self.module = self.url[len(self.base):] |
|
190 | self.module = self.url[len(self.base):] | |
189 | self.rootmodule = self.module |
|
191 | self.rootmodule = self.module | |
190 | self.commits = {} |
|
192 | self.commits = {} | |
@@ -535,24 +537,6 b' class svn_source(converter_source):' | |||||
535 | svn.ra.reparent(self.ra, svn_url.encode(self.encoding)) |
|
537 | svn.ra.reparent(self.ra, svn_url.encode(self.encoding)) | |
536 |
|
538 | |||
537 | def expandpaths(self, rev, paths, parents): |
|
539 | def expandpaths(self, rev, paths, parents): | |
538 | def get_entry_from_path(path, module=self.module): |
|
|||
539 | # Given the repository url of this wc, say |
|
|||
540 | # "http://server/plone/CMFPlone/branches/Plone-2_0-branch" |
|
|||
541 | # extract the "entry" portion (a relative path) from what |
|
|||
542 | # svn log --xml says, ie |
|
|||
543 | # "/CMFPlone/branches/Plone-2_0-branch/tests/PloneTestCase.py" |
|
|||
544 | # that is to say "tests/PloneTestCase.py" |
|
|||
545 | if path.startswith(module): |
|
|||
546 | relative = path[len(module):] |
|
|||
547 | if relative.startswith('/'): |
|
|||
548 | return relative[1:] |
|
|||
549 | else: |
|
|||
550 | return relative |
|
|||
551 |
|
||||
552 | # The path is outside our tracked tree... |
|
|||
553 | self.ui.debug('%r is not under %r, ignoring\n' % (path, module)) |
|
|||
554 | return None |
|
|||
555 |
|
||||
556 | entries = [] |
|
540 | entries = [] | |
557 | copyfrom = {} # Map of entrypath, revision for finding source of deleted revisions. |
|
541 | copyfrom = {} # Map of entrypath, revision for finding source of deleted revisions. | |
558 | copies = {} |
|
542 | copies = {} | |
@@ -563,24 +547,25 b' class svn_source(converter_source):' | |||||
563 | self.reparent(self.module) |
|
547 | self.reparent(self.module) | |
564 |
|
548 | |||
565 | for path, ent in paths: |
|
549 | for path, ent in paths: | |
566 |
entrypath = |
|
550 | entrypath = self.getrelpath(path) | |
567 | entry = entrypath.decode(self.encoding) |
|
551 | entry = entrypath.decode(self.encoding) | |
568 |
|
552 | |||
569 | kind = svn.ra.check_path(self.ra, entrypath, revnum) |
|
553 | kind = svn.ra.check_path(self.ra, entrypath, revnum) | |
570 | if kind == svn.core.svn_node_file: |
|
554 | if kind == svn.core.svn_node_file: | |
571 | if ent.copyfrom_path: |
|
|||
572 | copyfrom_path = get_entry_from_path(ent.copyfrom_path) |
|
|||
573 | if copyfrom_path: |
|
|||
574 | self.ui.debug("Copied to %s from %s@%s\n" % |
|
|||
575 | (entrypath, copyfrom_path, |
|
|||
576 | ent.copyfrom_rev)) |
|
|||
577 | # It's probably important for hg that the source |
|
|||
578 | # exists in the revision's parent, not just the |
|
|||
579 | # ent.copyfrom_rev |
|
|||
580 | fromkind = svn.ra.check_path(self.ra, copyfrom_path, ent.copyfrom_rev) |
|
|||
581 | if fromkind != 0: |
|
|||
582 | copies[self.recode(entry)] = self.recode(copyfrom_path) |
|
|||
583 | entries.append(self.recode(entry)) |
|
555 | entries.append(self.recode(entry)) | |
|
556 | if not ent.copyfrom_path or not parents: | |||
|
557 | continue | |||
|
558 | # Copy sources not in parent revisions cannot be represented, | |||
|
559 | # ignore their origin for now | |||
|
560 | pmodule, prevnum = self.revsplit(parents[0])[1:] | |||
|
561 | if ent.copyfrom_rev < prevnum: | |||
|
562 | continue | |||
|
563 | copyfrom_path = self.getrelpath(ent.copyfrom_path, pmodule) | |||
|
564 | if not copyfrom_path: | |||
|
565 | continue | |||
|
566 | self.ui.debug("copied to %s from %s@%s\n" % | |||
|
567 | (entrypath, copyfrom_path, ent.copyfrom_rev)) | |||
|
568 | copies[self.recode(entry)] = self.recode(copyfrom_path) | |||
584 | elif kind == 0: # gone, but had better be a deleted *file* |
|
569 | elif kind == 0: # gone, but had better be a deleted *file* | |
585 | self.ui.debug("gone from %s\n" % ent.copyfrom_rev) |
|
570 | self.ui.debug("gone from %s\n" % ent.copyfrom_rev) | |
586 |
|
571 | |||
@@ -590,8 +575,8 b' class svn_source(converter_source):' | |||||
590 | # a root revision. |
|
575 | # a root revision. | |
591 | uuid, old_module, fromrev = self.revsplit(parents[0]) |
|
576 | uuid, old_module, fromrev = self.revsplit(parents[0]) | |
592 |
|
577 | |||
593 |
basepath = old_module + "/" + |
|
578 | basepath = old_module + "/" + self.getrelpath(path) | |
594 | entrypath = old_module + "/" + get_entry_from_path(path, module=self.module) |
|
579 | entrypath = basepath | |
595 |
|
580 | |||
596 | def lookup_parts(p): |
|
581 | def lookup_parts(p): | |
597 | rc = None |
|
582 | rc = None | |
@@ -647,7 +632,7 b' class svn_source(converter_source):' | |||||
647 | # parent in the same commit? (probably can). Could |
|
632 | # parent in the same commit? (probably can). Could | |
648 | # cause problems if instead of revnum -1, |
|
633 | # cause problems if instead of revnum -1, | |
649 | # we have to look in (copyfrom_path, revnum - 1) |
|
634 | # we have to look in (copyfrom_path, revnum - 1) | |
650 |
entrypath = |
|
635 | entrypath = self.getrelpath("/" + child, module=old_module) | |
651 | if entrypath: |
|
636 | if entrypath: | |
652 | entry = self.recode(entrypath.decode(self.encoding)) |
|
637 | entry = self.recode(entrypath.decode(self.encoding)) | |
653 | if entry in copies: |
|
638 | if entry in copies: | |
@@ -680,7 +665,7 b' class svn_source(converter_source):' | |||||
680 | # parent in the same commit? (probably can). Could |
|
665 | # parent in the same commit? (probably can). Could | |
681 | # cause problems if instead of revnum -1, |
|
666 | # cause problems if instead of revnum -1, | |
682 | # we have to look in (copyfrom_path, revnum - 1) |
|
667 | # we have to look in (copyfrom_path, revnum - 1) | |
683 |
entrypath = |
|
668 | entrypath = self.getrelpath("/" + child) | |
684 | # print child, self.module, entrypath |
|
669 | # print child, self.module, entrypath | |
685 | if entrypath: |
|
670 | if entrypath: | |
686 | # Need to filter out directories here... |
|
671 | # Need to filter out directories here... | |
@@ -691,39 +676,30 b' class svn_source(converter_source):' | |||||
691 | # Copies here (must copy all from source) |
|
676 | # Copies here (must copy all from source) | |
692 | # Probably not a real problem for us if |
|
677 | # Probably not a real problem for us if | |
693 | # source does not exist |
|
678 | # source does not exist | |
694 |
|
679 | if not ent.copyfrom_path or not parents: | ||
695 | # Can do this with the copy command "hg copy" |
|
680 | continue | |
696 | # if ent.copyfrom_path: |
|
681 | # Copy sources not in parent revisions cannot be represented, | |
697 | # copyfrom_entry = get_entry_from_path(ent.copyfrom_path.decode(self.encoding), |
|
682 | # ignore their origin for now | |
698 | # module=self.module) |
|
683 | pmodule, prevnum = self.revsplit(parents[0])[1:] | |
699 | # copyto_entry = entrypath |
|
684 | if ent.copyfrom_rev < prevnum: | |
700 |
|
|
685 | continue | |
701 | # print "copy directory", copyfrom_entry, 'to', copyto_entry |
|
686 | copyfrompath = ent.copyfrom_path.decode(self.encoding) | |
702 | # |
|
687 | copyfrompath = self.getrelpath(copyfrompath, pmodule) | |
703 | # copies.append((copyfrom_entry, copyto_entry)) |
|
688 | if not copyfrompath: | |
704 |
|
689 | continue | ||
705 |
|
|
690 | copyfrom[path] = ent | |
706 | copyfrom_path = ent.copyfrom_path.decode(self.encoding) |
|
691 | self.ui.debug("mark %s came from %s:%d\n" | |
707 | copyfrom_entry = get_entry_from_path(copyfrom_path, module=self.module) |
|
692 | % (path, copyfrompath, ent.copyfrom_rev)) | |
708 | if copyfrom_entry: |
|
693 | children = self._find_children(ent.copyfrom_path, ent.copyfrom_rev) | |
709 | copyfrom[path] = ent |
|
694 | children.sort() | |
710 | self.ui.debug("mark %s came from %s\n" % (path, copyfrom[path])) |
|
695 | for child in children: | |
711 |
|
696 | entrypath = self.getrelpath("/" + child, pmodule) | ||
712 | # Good, /probably/ a regular copy. Really should check |
|
697 | if not entrypath: | |
713 | # to see whether the parent revision actually contains |
|
698 | continue | |
714 | # the directory in question. |
|
699 | entry = entrypath.decode(self.encoding) | |
715 | children = self._find_children(self.recode(copyfrom_path), ent.copyfrom_rev) |
|
700 | copytopath = path + entry[len(copyfrompath):] | |
716 | children.sort() |
|
701 | copytopath = self.getrelpath(copytopath) | |
717 | for child in children: |
|
702 | copies[self.recode(copytopath)] = self.recode(entry, pmodule) | |
718 | entrypath = get_entry_from_path("/" + child, module=self.module) |
|
|||
719 | if entrypath: |
|
|||
720 | entry = entrypath.decode(self.encoding) |
|
|||
721 | # print "COPY COPY From", copyfrom_entry, entry |
|
|||
722 | copyto_path = path + entry[len(copyfrom_entry):] |
|
|||
723 | copyto_entry = get_entry_from_path(copyto_path, module=self.module) |
|
|||
724 | # print "COPY", entry, "COPY To", copyto_entry |
|
|||
725 | copies[self.recode(copyto_entry)] = self.recode(entry) |
|
|||
726 | # copy from quux splort/quuxfile |
|
|||
727 |
|
703 | |||
728 | return (util.unique(entries), copies) |
|
704 | return (util.unique(entries), copies) | |
729 |
|
705 | |||
@@ -732,6 +708,13 b' class svn_source(converter_source):' | |||||
732 | from_revnum, to_revnum = to_revnum, from_revnum |
|
708 | from_revnum, to_revnum = to_revnum, from_revnum | |
733 |
|
709 | |||
734 | self.child_cset = None |
|
710 | self.child_cset = None | |
|
711 | ||||
|
712 | def isdescendantof(parent, child): | |||
|
713 | if not child or not parent or not child.startswith(parent): | |||
|
714 | return False | |||
|
715 | subpath = child[len(parent):] | |||
|
716 | return len(subpath) > 1 and subpath[0] == '/' | |||
|
717 | ||||
735 | def parselogentry(orig_paths, revnum, author, date, message): |
|
718 | def parselogentry(orig_paths, revnum, author, date, message): | |
736 | """Return the parsed commit object or None, and True if |
|
719 | """Return the parsed commit object or None, and True if | |
737 | the revision is a branch root. |
|
720 | the revision is a branch root. | |
@@ -755,10 +738,21 b' class svn_source(converter_source):' | |||||
755 | if root_paths: |
|
738 | if root_paths: | |
756 | path, ent = root_paths[-1] |
|
739 | path, ent = root_paths[-1] | |
757 | if ent.copyfrom_path: |
|
740 | if ent.copyfrom_path: | |
|
741 | # If dir was moved while one of its file was removed | |||
|
742 | # the log may look like: | |||
|
743 | # A /dir (from /dir:x) | |||
|
744 | # A /dir/a (from /dir/a:y) | |||
|
745 | # A /dir/b (from /dir/b:z) | |||
|
746 | # ... | |||
|
747 | # for all remaining children. | |||
|
748 | # Let's take the highest child element from rev as source. | |||
|
749 | copies = [(p,e) for p,e in orig_paths[:-1] | |||
|
750 | if isdescendantof(ent.copyfrom_path, e.copyfrom_path)] | |||
|
751 | fromrev = max([e.copyfrom_rev for p,e in copies] + [ent.copyfrom_rev]) | |||
758 | branched = True |
|
752 | branched = True | |
759 | newpath = ent.copyfrom_path + self.module[len(path):] |
|
753 | newpath = ent.copyfrom_path + self.module[len(path):] | |
760 | # ent.copyfrom_rev may not be the actual last revision |
|
754 | # ent.copyfrom_rev may not be the actual last revision | |
761 |
previd = self.latest(newpath, |
|
755 | previd = self.latest(newpath, fromrev) | |
762 | if previd is not None: |
|
756 | if previd is not None: | |
763 | prevmodule, prevnum = self.revsplit(previd)[1:] |
|
757 | prevmodule, prevnum = self.revsplit(previd)[1:] | |
764 | if prevnum >= self.startrev: |
|
758 | if prevnum >= self.startrev: | |
@@ -771,8 +765,7 b' class svn_source(converter_source):' | |||||
771 | paths = [] |
|
765 | paths = [] | |
772 | # filter out unrelated paths |
|
766 | # filter out unrelated paths | |
773 | for path, ent in orig_paths: |
|
767 | for path, ent in orig_paths: | |
774 | if not path.startswith(self.module): |
|
768 | if self.getrelpath(path) is None: | |
775 | self.ui.debug("boring@%s: %s\n" % (revnum, path)) |
|
|||
776 | continue |
|
769 | continue | |
777 | paths.append((path, ent)) |
|
770 | paths.append((path, ent)) | |
778 |
|
771 | |||
@@ -885,6 +878,26 b' class svn_source(converter_source):' | |||||
885 | rpath = '/'.join([self.base, path]).strip('/') |
|
878 | rpath = '/'.join([self.base, path]).strip('/') | |
886 | return ['%s/%s' % (path, x) for x in svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool).keys()] |
|
879 | return ['%s/%s' % (path, x) for x in svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool).keys()] | |
887 |
|
880 | |||
|
881 | def getrelpath(self, path, module=None): | |||
|
882 | if module is None: | |||
|
883 | module = self.module | |||
|
884 | # Given the repository url of this wc, say | |||
|
885 | # "http://server/plone/CMFPlone/branches/Plone-2_0-branch" | |||
|
886 | # extract the "entry" portion (a relative path) from what | |||
|
887 | # svn log --xml says, ie | |||
|
888 | # "/CMFPlone/branches/Plone-2_0-branch/tests/PloneTestCase.py" | |||
|
889 | # that is to say "tests/PloneTestCase.py" | |||
|
890 | if path.startswith(module): | |||
|
891 | relative = path.rstrip('/')[len(module):] | |||
|
892 | if relative.startswith('/'): | |||
|
893 | return relative[1:] | |||
|
894 | elif relative == '': | |||
|
895 | return relative | |||
|
896 | ||||
|
897 | # The path is outside our tracked tree... | |||
|
898 | self.ui.debug('%r is not under %r, ignoring\n' % (path, module)) | |||
|
899 | return None | |||
|
900 | ||||
888 | pre_revprop_change = '''#!/bin/sh |
|
901 | pre_revprop_change = '''#!/bin/sh | |
889 |
|
902 | |||
890 | REPOS="$1" |
|
903 | REPOS="$1" |
@@ -1018,11 +1018,16 b' def walkchangerevs(ui, repo, pats, chang' | |||||
1018 | minrev, maxrev = min(revs), max(revs) |
|
1018 | minrev, maxrev = min(revs), max(revs) | |
1019 | for file_, node in iterfiles(): |
|
1019 | for file_, node in iterfiles(): | |
1020 | filelog = repo.file(file_) |
|
1020 | filelog = repo.file(file_) | |
1021 | # A zero count may be a directory or deleted file, so |
|
|||
1022 | # try to find matching entries on the slow path. |
|
|||
1023 | if filelog.count() == 0: |
|
1021 | if filelog.count() == 0: | |
1024 |
|
|
1022 | if node is None: | |
1025 | break |
|
1023 | # A zero count may be a directory or deleted file, so | |
|
1024 | # try to find matching entries on the slow path. | |||
|
1025 | slowpath = True | |||
|
1026 | break | |||
|
1027 | else: | |||
|
1028 | ui.warn(_('%s:%s copy source revision cannot be found!\n') | |||
|
1029 | % (file_, short(node))) | |||
|
1030 | continue | |||
1026 | for rev, copied in filerevgen(filelog, node): |
|
1031 | for rev, copied in filerevgen(filelog, node): | |
1027 | if rev <= maxrev: |
|
1032 | if rev <= maxrev: | |
1028 | if rev < minrev: |
|
1033 | if rev < minrev: |
@@ -712,17 +712,17 b' class localrepository(repo.repository):' | |||||
712 | # |
|
712 | # | |
713 | meta["copy"] = cp |
|
713 | meta["copy"] = cp | |
714 | if not manifest2: # not a branch merge |
|
714 | if not manifest2: # not a branch merge | |
715 |
meta["copyrev"] = hex(manifest1 |
|
715 | meta["copyrev"] = hex(manifest1[cp]) | |
716 | fp2 = nullid |
|
716 | fp2 = nullid | |
717 | elif fp2 != nullid: # copied on remote side |
|
717 | elif fp2 != nullid: # copied on remote side | |
718 |
meta["copyrev"] = hex(manifest1 |
|
718 | meta["copyrev"] = hex(manifest1[cp]) | |
719 | elif fp1 != nullid: # copied on local side, reversed |
|
719 | elif fp1 != nullid: # copied on local side, reversed | |
720 |
meta["copyrev"] = hex(manifest2 |
|
720 | meta["copyrev"] = hex(manifest2[cp]) | |
721 | fp2 = fp1 |
|
721 | fp2 = fp1 | |
722 | elif cp in manifest2: # directory rename on local side |
|
722 | elif cp in manifest2: # directory rename on local side | |
723 | meta["copyrev"] = hex(manifest2[cp]) |
|
723 | meta["copyrev"] = hex(manifest2[cp]) | |
724 | else: # directory rename on remote side |
|
724 | else: # directory rename on remote side | |
725 |
meta["copyrev"] = hex(manifest1 |
|
725 | meta["copyrev"] = hex(manifest1[cp]) | |
726 | self.ui.debug(_(" %s: copy %s:%s\n") % |
|
726 | self.ui.debug(_(" %s: copy %s:%s\n") % | |
727 | (fn, cp, meta["copyrev"])) |
|
727 | (fn, cp, meta["copyrev"])) | |
728 | fp1 = nullid |
|
728 | fp1 = nullid |
@@ -245,7 +245,14 b' def _verify(repo):' | |||||
245 | rp = fl.renamed(n) |
|
245 | rp = fl.renamed(n) | |
246 | if rp: |
|
246 | if rp: | |
247 | fl2 = repo.file(rp[0]) |
|
247 | fl2 = repo.file(rp[0]) | |
248 |
|
|
248 | if fl2.count() == 0: | |
|
249 | err(flr, _("empty or missing copy source revlog %s:%s") | |||
|
250 | % (rp[0], short(rp[1])), f) | |||
|
251 | elif rp[1] == nullid: | |||
|
252 | err(flr, _("copy source revision is nullid %s:%s") | |||
|
253 | % (rp[0], short(rp[1])), f) | |||
|
254 | else: | |||
|
255 | rev = fl2.rev(rp[1]) | |||
249 | except KeyboardInterrupt: |
|
256 | except KeyboardInterrupt: | |
250 | repo.ui.warn(_("interrupted")) |
|
257 | repo.ui.warn(_("interrupted")) | |
251 | raise |
|
258 | raise |
@@ -35,41 +35,48 b' svn import -m "init projA" projA $svnurl' | |||||
35 | echo % update svn repository |
|
35 | echo % update svn repository | |
36 | svn co $svnurl A | fix_path |
|
36 | svn co $svnurl A | fix_path | |
37 | cd A |
|
37 | cd A | |
38 |
echo |
|
38 | echo a > trunk/a | |
39 |
echo |
|
39 | echo b > trunk/b | |
40 |
echo |
|
40 | echo c > trunk/c | |
41 | # Add a file within branches, used to confuse branch detection |
|
41 | # Add a file within branches, used to confuse branch detection | |
42 |
echo |
|
42 | echo d > branches/notinbranch | |
43 |
svn add trunk/ |
|
43 | svn add trunk/a trunk/b trunk/c branches/notinbranch | |
44 | svn ci -m hello |
|
44 | svn ci -m hello | |
45 |
|
45 | |||
46 |
echo % branch to old |
|
46 | echo % branch to old | |
47 | svn copy trunk branches/old |
|
47 | svn copy trunk branches/old | |
48 |
svn rm branches/old/ |
|
48 | svn rm branches/old/c | |
49 |
svn ci -m "branch trunk, remove |
|
49 | svn ci -m "branch trunk, remove c" | |
50 | svn up |
|
50 | svn up | |
51 |
|
51 | |||
52 | echo % update trunk |
|
52 | echo % update trunk | |
53 |
"$TESTDIR/svn-safe-append.py" |
|
53 | "$TESTDIR/svn-safe-append.py" a trunk/a | |
54 |
svn ci -m "change |
|
54 | svn ci -m "change a" | |
55 |
|
55 | |||
56 | echo % update old branch |
|
56 | echo % update old branch | |
57 |
"$TESTDIR/svn-safe-append.py" |
|
57 | "$TESTDIR/svn-safe-append.py" b branches/old/b | |
58 |
svn ci -m "change |
|
58 | svn ci -m "change b" | |
59 |
|
59 | |||
60 | echo % create a cross-branch revision |
|
60 | echo % create a cross-branch revision | |
61 |
svn move -m "move |
|
61 | svn move -m "move b" trunk/b branches/old/c | |
62 | branches/old/letter3.txt |
|
62 | "$TESTDIR/svn-safe-append.py" c branches/old/c | |
63 | "$TESTDIR/svn-safe-append.py" "I am fine" branches/old/letter3.txt |
|
63 | svn ci -m "move and update c" | |
64 | svn ci -m "move and update letter3.txt" |
|
|||
65 |
|
64 | |||
66 | echo % update old branch again |
|
65 | echo % update old branch again | |
67 |
"$TESTDIR/svn-safe-append.py" |
|
66 | "$TESTDIR/svn-safe-append.py" b branches/old/b | |
68 |
svn ci -m "change |
|
67 | svn ci -m "change b again" | |
|
68 | ||||
|
69 | echo % move back and forth between branch of similar names | |||
|
70 | # This used to generate fake copy records | |||
|
71 | svn up | |||
|
72 | svn move branches/old branches/old2 | |||
|
73 | svn ci -m "move to old2" | |||
|
74 | svn move branches/old2 branches/old | |||
|
75 | svn ci -m "move back to old" | |||
69 |
|
76 | |||
70 | echo % update trunk again |
|
77 | echo % update trunk again | |
71 |
"$TESTDIR/svn-safe-append.py" |
|
78 | "$TESTDIR/svn-safe-append.py" a trunk/a | |
72 |
svn ci -m "last change to |
|
79 | svn ci -m "last change to a" | |
73 | cd .. |
|
80 | cd .. | |
74 |
|
81 | |||
75 | echo % convert trunk and branches |
|
82 | echo % convert trunk and branches | |
@@ -77,15 +84,15 b' hg convert --datesort $svnurl A-hg' | |||||
77 |
|
84 | |||
78 | echo % branch again from a converted revision |
|
85 | echo % branch again from a converted revision | |
79 | cd A |
|
86 | cd A | |
80 |
svn copy -r 1 $svnurl/trunk branches/old |
|
87 | svn copy -r 1 $svnurl/trunk branches/old3 | |
81 |
svn ci -m "branch trunk@1 into old |
|
88 | svn ci -m "branch trunk@1 into old3" | |
82 | cd .. |
|
89 | cd .. | |
83 |
|
90 | |||
84 | echo % convert again |
|
91 | echo % convert again | |
85 | hg convert --datesort $svnurl A-hg |
|
92 | hg convert --datesort $svnurl A-hg | |
86 |
|
93 | |||
87 | cd A-hg |
|
94 | cd A-hg | |
88 | hg glog --template '#rev# #desc|firstline# files: #files#\n' |
|
95 | hg glog --template 'branch=#branches# #rev# #desc|firstline# files: #files#\n' | |
89 | hg branches | sed 's/:.*/:/' |
|
96 | hg branches | sed 's/:.*/:/' | |
90 | hg tags -q |
|
97 | hg tags -q | |
91 | cd .. |
|
98 | cd .. |
@@ -9,95 +9,122 b' A A/trunk' | |||||
9 | A A/branches |
|
9 | A A/branches | |
10 | A A/tags |
|
10 | A A/tags | |
11 | Checked out revision 1. |
|
11 | Checked out revision 1. | |
12 |
A trunk/ |
|
12 | A trunk/a | |
13 |
A trunk/ |
|
13 | A trunk/b | |
14 |
A trunk/ |
|
14 | A trunk/c | |
15 |
A branches/ |
|
15 | A branches/notinbranch | |
16 |
Adding branches/ |
|
16 | Adding branches/notinbranch | |
17 |
Adding trunk/ |
|
17 | Adding trunk/a | |
18 |
Adding trunk/ |
|
18 | Adding trunk/b | |
19 |
Adding trunk/ |
|
19 | Adding trunk/c | |
20 | Transmitting file data .... |
|
20 | Transmitting file data .... | |
21 | Committed revision 2. |
|
21 | Committed revision 2. | |
22 |
% branch to old |
|
22 | % branch to old | |
23 | A branches/old |
|
23 | A branches/old | |
24 |
D branches/old/ |
|
24 | D branches/old/c | |
25 | Adding branches/old |
|
25 | Adding branches/old | |
26 |
Adding branches/old/ |
|
26 | Adding branches/old/a | |
27 |
Adding branches/old/ |
|
27 | Adding branches/old/b | |
28 |
Deleting branches/old/ |
|
28 | Deleting branches/old/c | |
29 |
|
29 | |||
30 | Committed revision 3. |
|
30 | Committed revision 3. | |
31 | At revision 3. |
|
31 | At revision 3. | |
32 | % update trunk |
|
32 | % update trunk | |
33 |
Sending trunk/ |
|
33 | Sending trunk/a | |
34 | Transmitting file data . |
|
34 | Transmitting file data . | |
35 | Committed revision 4. |
|
35 | Committed revision 4. | |
36 | % update old branch |
|
36 | % update old branch | |
37 |
Sending branches/old/ |
|
37 | Sending branches/old/b | |
38 | Transmitting file data . |
|
38 | Transmitting file data . | |
39 | Committed revision 5. |
|
39 | Committed revision 5. | |
40 | % create a cross-branch revision |
|
40 | % create a cross-branch revision | |
41 |
A branches/old/ |
|
41 | A branches/old/c | |
42 |
D trunk/ |
|
42 | D trunk/b | |
43 |
Adding branches/old/ |
|
43 | Adding branches/old/c | |
44 |
Deleting trunk/ |
|
44 | Deleting trunk/b | |
45 | Transmitting file data . |
|
45 | Transmitting file data . | |
46 | Committed revision 6. |
|
46 | Committed revision 6. | |
47 | % update old branch again |
|
47 | % update old branch again | |
48 |
Sending branches/old/ |
|
48 | Sending branches/old/b | |
49 | Transmitting file data . |
|
49 | Transmitting file data . | |
50 | Committed revision 7. |
|
50 | Committed revision 7. | |
|
51 | % move back and forth between branch of similar names | |||
|
52 | At revision 7. | |||
|
53 | A branches/old2 | |||
|
54 | D branches/old/a | |||
|
55 | D branches/old/b | |||
|
56 | D branches/old/c | |||
|
57 | D branches/old | |||
|
58 | Deleting branches/old | |||
|
59 | Adding branches/old2 | |||
|
60 | ||||
|
61 | Committed revision 8. | |||
|
62 | A branches/old | |||
|
63 | D branches/old2/a | |||
|
64 | D branches/old2/b | |||
|
65 | D branches/old2/c | |||
|
66 | D branches/old2 | |||
|
67 | Adding branches/old | |||
|
68 | Deleting branches/old2 | |||
|
69 | ||||
|
70 | Committed revision 9. | |||
51 | % update trunk again |
|
71 | % update trunk again | |
52 |
Sending trunk/ |
|
72 | Sending trunk/a | |
53 | Transmitting file data . |
|
73 | Transmitting file data . | |
54 |
Committed revision |
|
74 | Committed revision 10. | |
55 | % convert trunk and branches |
|
75 | % convert trunk and branches | |
56 | initializing destination A-hg repository |
|
76 | initializing destination A-hg repository | |
57 | scanning source... |
|
77 | scanning source... | |
58 | sorting... |
|
78 | sorting... | |
59 | converting... |
|
79 | converting... | |
60 |
|
|
80 | 10 init projA | |
61 |
|
|
81 | 9 hello | |
62 |
|
|
82 | 8 branch trunk, remove c | |
63 |
|
|
83 | 7 change a | |
64 |
|
|
84 | 6 change b | |
65 |
|
|
85 | 5 move and update c | |
66 |
|
|
86 | 4 move and update c | |
67 |
|
|
87 | 3 change b again | |
68 | 0 last change to letter |
|
88 | 2 move to old2 | |
|
89 | 1 move back to old | |||
|
90 | 0 last change to a | |||
69 | % branch again from a converted revision |
|
91 | % branch again from a converted revision | |
70 | Checked out revision 1. |
|
92 | Checked out revision 1. | |
71 |
A branches/old |
|
93 | A branches/old3 | |
72 |
Adding branches/old |
|
94 | Adding branches/old3 | |
73 |
|
95 | |||
74 |
Committed revision |
|
96 | Committed revision 11. | |
75 | % convert again |
|
97 | % convert again | |
76 | scanning source... |
|
98 | scanning source... | |
77 | sorting... |
|
99 | sorting... | |
78 | converting... |
|
100 | converting... | |
79 |
0 branch trunk@1 into old |
|
101 | 0 branch trunk@1 into old3 | |
80 |
o |
|
102 | o branch=old3 11 branch trunk@1 into old3 files: | |
81 | | |
|
103 | | | |
82 |
| o |
|
104 | | o branch= 10 last change to a files: a | |
83 | | | |
|
105 | | | | |
84 | | | o 7 change letter2 again files: letter2.txt |
|
106 | | | o branch=old 9 move back to old files: | |
85 | | | | |
|
107 | | | | | |
86 | | o | 6 move and update letter3.txt files: letter2.txt |
|
108 | | | o branch=old2 8 move to old2 files: | |
87 | | | | |
|
109 | | | | | |
88 | | | o 5 move and update letter3.txt files: letter3.txt |
|
110 | | | o branch=old 7 change b again files: b | |
89 | | | | |
|
111 | | | | | |
90 | | | o 4 change letter2 files: letter2.txt |
|
112 | | o | branch= 6 move and update c files: b | |
|
113 | | | | | |||
|
114 | | | o branch=old 5 move and update c files: c | |||
91 | | | | |
|
115 | | | | | |
92 | | o | 3 change letter files: letter.txt |
|
116 | | | o branch=old 4 change b files: b | |
|
117 | | | | | |||
|
118 | | o | branch= 3 change a files: a | |||
93 | | | | |
|
119 | | | | | |
94 | +---o 2 branch trunk, remove letter3 files: letter.txt letter2.txt |
|
120 | | | o branch=old 2 branch trunk, remove c files: a b | |
95 | | | |
|
121 | | |/ | |
96 | | o 1 hello files: letter.txt letter2.txt letter3.txt |
|
122 | | o branch= 1 hello files: a b c | |
97 | |/ |
|
123 | |/ | |
98 | o 0 init projA files: |
|
124 | o branch= 0 init projA files: | |
99 |
|
125 | |||
100 |
old |
|
126 | old3 11: | |
101 |
default |
|
127 | default 10: | |
102 |
old |
|
128 | old 9: | |
|
129 | old2 8: | |||
103 | tip |
|
130 | tip |
@@ -27,8 +27,10 b' cd projA' | |||||
27 | mkdir trunk |
|
27 | mkdir trunk | |
28 | echo a > trunk/a |
|
28 | echo a > trunk/a | |
29 | mkdir trunk/d1 |
|
29 | mkdir trunk/d1 | |
|
30 | mkdir trunk/d2 | |||
30 | echo b > trunk/d1/b |
|
31 | echo b > trunk/d1/b | |
31 | echo c > trunk/d1/c |
|
32 | echo c > trunk/d1/c | |
|
33 | echo d > trunk/d2/d | |||
32 | cd .. |
|
34 | cd .. | |
33 |
|
35 | |||
34 | svnurl=file://$svnpath/svn-repo/projA |
|
36 | svnurl=file://$svnpath/svn-repo/projA | |
@@ -50,10 +52,16 b' mkdir subproject/branches' | |||||
50 | svn add subproject/branches |
|
52 | svn add subproject/branches | |
51 | svn ci -m createbranches |
|
53 | svn ci -m createbranches | |
52 | svn mv $svnurl/subproject/d1 $svnurl/subproject/trunk/d1 -m moved1 |
|
54 | svn mv $svnurl/subproject/d1 $svnurl/subproject/trunk/d1 -m moved1 | |
|
55 | svn mv $svnurl/subproject/d2 $svnurl/subproject/trunk/d2 -m moved2 | |||
53 | svn up |
|
56 | svn up | |
54 | "$TESTDIR/svn-safe-append.py" b subproject/trunk/d1/b |
|
57 | "$TESTDIR/svn-safe-append.py" b subproject/trunk/d1/b | |
55 | svn ci -m changeb |
|
58 | svn rm subproject/trunk/d2 | |
|
59 | svn ci -m "changeb and rm d2" | |||
56 | svn mv $svnurl/subproject/trunk/d1 $svnurl/subproject/branches/d1 -m moved1again |
|
60 | svn mv $svnurl/subproject/trunk/d1 $svnurl/subproject/branches/d1 -m moved1again | |
|
61 | echo % copy a file from a past revision | |||
|
62 | svn copy -r 7 $svnurl/subproject/trunk/d2/d $svnurl/subproject/trunk -m copyfilefrompast | |||
|
63 | echo % copy a directory from a past revision | |||
|
64 | svn copy -r 7 $svnurl/subproject/trunk/d2 $svnurl/subproject/trunk -m copydirfrompast | |||
57 | cd .. |
|
65 | cd .. | |
58 |
|
66 | |||
59 | echo % convert trunk and branches |
|
67 | echo % convert trunk and branches |
@@ -4,6 +4,8 b' Adding projA/trunk/a' | |||||
4 | Adding projA/trunk/d1 |
|
4 | Adding projA/trunk/d1 | |
5 | Adding projA/trunk/d1/b |
|
5 | Adding projA/trunk/d1/b | |
6 | Adding projA/trunk/d1/c |
|
6 | Adding projA/trunk/d1/c | |
|
7 | Adding projA/trunk/d2 | |||
|
8 | Adding projA/trunk/d2/d | |||
7 |
|
9 | |||
8 | Committed revision 1. |
|
10 | Committed revision 1. | |
9 | % update svn repository |
|
11 | % update svn repository | |
@@ -12,6 +14,8 b' A A/trunk/a' | |||||
12 | A A/trunk/d1 |
|
14 | A A/trunk/d1 | |
13 | A A/trunk/d1/b |
|
15 | A A/trunk/d1/b | |
14 | A A/trunk/d1/c |
|
16 | A A/trunk/d1/c | |
|
17 | A A/trunk/d2 | |||
|
18 | A A/trunk/d2/d | |||
15 | Checked out revision 1. |
|
19 | Checked out revision 1. | |
16 | Sending trunk/a |
|
20 | Sending trunk/a | |
17 | Sending trunk/d1/c |
|
21 | Sending trunk/d1/c | |
@@ -25,6 +29,8 b' A subproject/a' | |||||
25 | A subproject/d1 |
|
29 | A subproject/d1 | |
26 | A subproject/d1/b |
|
30 | A subproject/d1/b | |
27 | A subproject/d1/c |
|
31 | A subproject/d1/c | |
|
32 | A subproject/d2 | |||
|
33 | A subproject/d2/d | |||
28 | Updated to revision 3. |
|
34 | Updated to revision 3. | |
29 | A subproject/trunk |
|
35 | A subproject/trunk | |
30 | Adding subproject/trunk |
|
36 | Adding subproject/trunk | |
@@ -36,35 +42,58 b' Adding subproject/branches' | |||||
36 | Committed revision 5. |
|
42 | Committed revision 5. | |
37 |
|
43 | |||
38 | Committed revision 6. |
|
44 | Committed revision 6. | |
|
45 | ||||
|
46 | Committed revision 7. | |||
39 | A subproject/trunk/d1 |
|
47 | A subproject/trunk/d1 | |
40 | A subproject/trunk/d1/b |
|
48 | A subproject/trunk/d1/b | |
41 | A subproject/trunk/d1/c |
|
49 | A subproject/trunk/d1/c | |
|
50 | A subproject/trunk/d2 | |||
|
51 | A subproject/trunk/d2/d | |||
42 | D subproject/d1 |
|
52 | D subproject/d1 | |
43 | Updated to revision 6. |
|
53 | D subproject/d2 | |
|
54 | Updated to revision 7. | |||
|
55 | D subproject/trunk/d2/d | |||
|
56 | D subproject/trunk/d2 | |||
44 | Sending subproject/trunk/d1/b |
|
57 | Sending subproject/trunk/d1/b | |
|
58 | Deleting subproject/trunk/d2 | |||
45 | Transmitting file data . |
|
59 | Transmitting file data . | |
46 |
Committed revision |
|
60 | Committed revision 8. | |
|
61 | ||||
|
62 | Committed revision 9. | |||
|
63 | % copy a file from a past revision | |||
47 |
|
64 | |||
48 |
Committed revision |
|
65 | Committed revision 10. | |
|
66 | % copy a directory from a past revision | |||
|
67 | ||||
|
68 | Committed revision 11. | |||
49 | % convert trunk and branches |
|
69 | % convert trunk and branches | |
50 | initializing destination A-hg repository |
|
70 | initializing destination A-hg repository | |
51 | scanning source... |
|
71 | scanning source... | |
52 | sorting... |
|
72 | sorting... | |
53 | converting... |
|
73 | converting... | |
54 |
|
|
74 | 9 createtrunk | |
55 |
|
|
75 | 8 moved1 | |
56 |
|
|
76 | 7 moved1 | |
57 | 3 changeb |
|
77 | 6 moved2 | |
58 | 2 changeb |
|
78 | 5 changeb and rm d2 | |
59 | 1 moved1again |
|
79 | 4 changeb and rm d2 | |
60 |
|
|
80 | 3 moved1again | |
61 | o 6 moved1again files: d1/b d1/c |
|
81 | 2 moved1again | |
|
82 | 1 copyfilefrompast | |||
|
83 | 0 copydirfrompast | |||
|
84 | o 9 copydirfrompast files: d2/d | |||
62 | | |
|
85 | | | |
63 | | o 5 moved1again files: |
|
86 | o 8 copyfilefrompast files: d | |
|
87 | | | |||
|
88 | o 7 moved1again files: d1/b d1/c | |||
|
89 | | | |||
|
90 | | o 6 moved1again files: | |||
64 | | | |
|
91 | | | | |
65 |
o | |
|
92 | o | 5 changeb and rm d2 files: d1/b d2/d | |
66 | | | |
|
93 | | | | |
67 |
| o |
|
94 | | o 4 changeb and rm d2 files: b | |
|
95 | | | | |||
|
96 | o | 3 moved2 files: d2/d | |||
68 | | | |
|
97 | | | | |
69 | o | 2 moved1 files: d1/b d1/c |
|
98 | o | 2 moved1 files: d1/b d1/c | |
70 | | | |
|
99 | | | | |
@@ -72,5 +101,5 b' o | 2 moved1 files: d1/b d1/c' | |||||
72 | | |
|
101 | | | |
73 | o 0 createtrunk files: |
|
102 | o 0 createtrunk files: | |
74 |
|
103 | |||
75 |
default |
|
104 | default 9: | |
76 |
d1 |
|
105 | d1 6: |
General Comments 0
You need to be logged in to leave comments.
Login now