Show More
@@ -0,0 +1,77 b'' | |||||
|
1 | #!/bin/sh | |||
|
2 | # check that renames are correctly saved by a commit after a merge | |||
|
3 | ||||
|
4 | HGMERGE=merge | |||
|
5 | export HGMERGE | |||
|
6 | ||||
|
7 | # test with the merge on 3 having the rename on the local parent | |||
|
8 | hg init a | |||
|
9 | cd a | |||
|
10 | ||||
|
11 | echo line1 > foo | |||
|
12 | hg add foo | |||
|
13 | hg ci -m '0: add foo' -d '0 0' | |||
|
14 | ||||
|
15 | echo line2 >> foo | |||
|
16 | hg ci -m '1: change foo' -d '0 0' | |||
|
17 | ||||
|
18 | hg up -C 0 | |||
|
19 | hg mv foo bar | |||
|
20 | rm bar | |||
|
21 | echo line0 > bar | |||
|
22 | echo line1 >> bar | |||
|
23 | hg ci -m '2: mv foo bar; change bar' -d '0 0' | |||
|
24 | ||||
|
25 | hg merge 1 | |||
|
26 | echo '% contents of bar should be line0 line1 line2' | |||
|
27 | cat bar | |||
|
28 | hg ci -m '3: merge with local rename' -d '0 0' | |||
|
29 | hg debugindex .hg/store/data/bar.i | |||
|
30 | hg debugrename bar | |||
|
31 | hg debugindex .hg/store/data/foo.i | |||
|
32 | ||||
|
33 | # revert the content change from rev 2 | |||
|
34 | hg up -C 2 | |||
|
35 | rm bar | |||
|
36 | echo line1 > bar | |||
|
37 | hg ci -m '4: revert content change from rev 2' -d '0 0' | |||
|
38 | ||||
|
39 | hg log --template '#rev#:#node|short# #parents#\n' | |||
|
40 | echo '% this should use bar@rev2 as the ancestor' | |||
|
41 | hg --debug merge 3 | |||
|
42 | echo '% contents of bar should be line1 line2' | |||
|
43 | cat bar | |||
|
44 | hg ci -m '5: merge' -d '0 0' | |||
|
45 | hg debugindex .hg/store/data/bar.i | |||
|
46 | ||||
|
47 | ||||
|
48 | # same thing, but with the merge on 3 having the rename on the remote parent | |||
|
49 | echo | |||
|
50 | echo | |||
|
51 | cd .. | |||
|
52 | hg clone -U -r 1 -r 2 a b | |||
|
53 | cd b | |||
|
54 | ||||
|
55 | hg up -C 1 | |||
|
56 | hg merge 2 | |||
|
57 | echo '% contents of bar should be line0 line1 line2' | |||
|
58 | cat bar | |||
|
59 | hg ci -m '3: merge with remote rename' -d '0 0' | |||
|
60 | hg debugindex .hg/store/data/bar.i | |||
|
61 | hg debugrename bar | |||
|
62 | hg debugindex .hg/store/data/foo.i | |||
|
63 | ||||
|
64 | # revert the content change from rev 2 | |||
|
65 | hg up -C 2 | |||
|
66 | rm bar | |||
|
67 | echo line1 > bar | |||
|
68 | hg ci -m '4: revert content change from rev 2' -d '0 0' | |||
|
69 | ||||
|
70 | hg log --template '#rev#:#node|short# #parents#\n' | |||
|
71 | echo '% this should use bar@rev2 as the ancestor' | |||
|
72 | hg --debug merge 3 | |||
|
73 | echo '% contents of bar should be line1 line2' | |||
|
74 | cat bar | |||
|
75 | hg ci -m '5: merge' -d '0 0' | |||
|
76 | hg debugindex .hg/store/data/bar.i | |||
|
77 |
@@ -0,0 +1,83 b'' | |||||
|
1 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
2 | merging bar and foo | |||
|
3 | 0 files updated, 1 files merged, 0 files removed, 0 files unresolved | |||
|
4 | (branch merge, don't forget to commit) | |||
|
5 | % contents of bar should be line0 line1 line2 | |||
|
6 | line0 | |||
|
7 | line1 | |||
|
8 | line2 | |||
|
9 | rev offset length base linkrev nodeid p1 p2 | |||
|
10 | 0 0 77 0 2 da78c0659611 000000000000 000000000000 | |||
|
11 | 1 77 76 0 3 4b358025380b 000000000000 da78c0659611 | |||
|
12 | bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2 | |||
|
13 | rev offset length base linkrev nodeid p1 p2 | |||
|
14 | 0 0 7 0 0 690b295714ae 000000000000 000000000000 | |||
|
15 | 1 7 13 1 1 9e25c27b8757 690b295714ae 000000000000 | |||
|
16 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
17 | 4:2d2f9a22c82b 2:0a3ab4856510 | |||
|
18 | 3:7d3b554bfdf1 2:0a3ab4856510 1:5cd961e4045d | |||
|
19 | 2:0a3ab4856510 0:2665aaee66e9 | |||
|
20 | 1:5cd961e4045d | |||
|
21 | 0:2665aaee66e9 | |||
|
22 | % this should use bar@rev2 as the ancestor | |||
|
23 | resolving manifests | |||
|
24 | overwrite None partial False | |||
|
25 | ancestor 0a3ab4856510 local 2d2f9a22c82b+ remote 7d3b554bfdf1 | |||
|
26 | bar: versions differ -> m | |||
|
27 | merging bar | |||
|
28 | my bar@2d2f9a22c82b+ other bar@7d3b554bfdf1 ancestor bar@0a3ab4856510 | |||
|
29 | 0 files updated, 1 files merged, 0 files removed, 0 files unresolved | |||
|
30 | (branch merge, don't forget to commit) | |||
|
31 | % contents of bar should be line1 line2 | |||
|
32 | line1 | |||
|
33 | line2 | |||
|
34 | rev offset length base linkrev nodeid p1 p2 | |||
|
35 | 0 0 77 0 2 da78c0659611 000000000000 000000000000 | |||
|
36 | 1 77 76 0 3 4b358025380b 000000000000 da78c0659611 | |||
|
37 | 2 153 7 2 4 4defe5eec418 da78c0659611 000000000000 | |||
|
38 | 3 160 13 3 5 4663501da27b 4defe5eec418 4b358025380b | |||
|
39 | ||||
|
40 | ||||
|
41 | requesting all changes | |||
|
42 | adding changesets | |||
|
43 | adding manifests | |||
|
44 | adding file changes | |||
|
45 | added 3 changesets with 3 changes to 2 files (+1 heads) | |||
|
46 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
47 | merging foo and bar | |||
|
48 | 0 files updated, 1 files merged, 0 files removed, 0 files unresolved | |||
|
49 | (branch merge, don't forget to commit) | |||
|
50 | % contents of bar should be line0 line1 line2 | |||
|
51 | line0 | |||
|
52 | line1 | |||
|
53 | line2 | |||
|
54 | rev offset length base linkrev nodeid p1 p2 | |||
|
55 | 0 0 77 0 2 da78c0659611 000000000000 000000000000 | |||
|
56 | 1 77 76 0 3 4b358025380b 000000000000 da78c0659611 | |||
|
57 | bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2 | |||
|
58 | rev offset length base linkrev nodeid p1 p2 | |||
|
59 | 0 0 7 0 0 690b295714ae 000000000000 000000000000 | |||
|
60 | 1 7 13 1 1 9e25c27b8757 690b295714ae 000000000000 | |||
|
61 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
62 | 4:2d2f9a22c82b 2:0a3ab4856510 | |||
|
63 | 3:96ab80c60897 1:5cd961e4045d 2:0a3ab4856510 | |||
|
64 | 2:0a3ab4856510 0:2665aaee66e9 | |||
|
65 | 1:5cd961e4045d | |||
|
66 | 0:2665aaee66e9 | |||
|
67 | % this should use bar@rev2 as the ancestor | |||
|
68 | resolving manifests | |||
|
69 | overwrite None partial False | |||
|
70 | ancestor 0a3ab4856510 local 2d2f9a22c82b+ remote 96ab80c60897 | |||
|
71 | bar: versions differ -> m | |||
|
72 | merging bar | |||
|
73 | my bar@2d2f9a22c82b+ other bar@96ab80c60897 ancestor bar@0a3ab4856510 | |||
|
74 | 0 files updated, 1 files merged, 0 files removed, 0 files unresolved | |||
|
75 | (branch merge, don't forget to commit) | |||
|
76 | % contents of bar should be line1 line2 | |||
|
77 | line1 | |||
|
78 | line2 | |||
|
79 | rev offset length base linkrev nodeid p1 p2 | |||
|
80 | 0 0 77 0 2 da78c0659611 000000000000 000000000000 | |||
|
81 | 1 77 76 0 3 4b358025380b 000000000000 da78c0659611 | |||
|
82 | 2 153 7 2 4 4defe5eec418 da78c0659611 000000000000 | |||
|
83 | 3 160 13 3 5 4663501da27b 4defe5eec418 4b358025380b |
@@ -439,6 +439,9 b' ui::' | |||||
439 | The committer of a changeset created when running "commit". |
|
439 | The committer of a changeset created when running "commit". | |
440 | Typically a person's name and email address, e.g. "Fred Widget |
|
440 | Typically a person's name and email address, e.g. "Fred Widget | |
441 | <fred@example.com>". Default is $EMAIL or username@hostname. |
|
441 | <fred@example.com>". Default is $EMAIL or username@hostname. | |
|
442 | If the username in hgrc is empty, it has to be specified manually or | |||
|
443 | in a different hgrc file (e.g. $HOME/.hgrc, if the admin set "username =" | |||
|
444 | in the system hgrc). | |||
442 | verbose;; |
|
445 | verbose;; | |
443 | Increase the amount of output printed. True or False. Default is False. |
|
446 | Increase the amount of output printed. True or False. Default is False. | |
444 |
|
447 |
@@ -125,7 +125,7 b' def make_file(repo, pat, node=None,' | |||||
125 | pathname), |
|
125 | pathname), | |
126 | mode) |
|
126 | mode) | |
127 |
|
127 | |||
128 | def matchpats(repo, pats=[], opts={}, head=''): |
|
128 | def matchpats(repo, pats=[], opts={}, head='', globbed=False): | |
129 | cwd = repo.getcwd() |
|
129 | cwd = repo.getcwd() | |
130 | if not pats and cwd: |
|
130 | if not pats and cwd: | |
131 | opts['include'] = [os.path.join(cwd, i) |
|
131 | opts['include'] = [os.path.join(cwd, i) | |
@@ -134,10 +134,12 b' def matchpats(repo, pats=[], opts={}, he' | |||||
134 | for x in opts.get('exclude', [])] |
|
134 | for x in opts.get('exclude', [])] | |
135 | cwd = '' |
|
135 | cwd = '' | |
136 | return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'), |
|
136 | return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'), | |
137 | opts.get('exclude'), head) |
|
137 | opts.get('exclude'), head, globbed=globbed) | |
138 |
|
138 | |||
139 |
def walk(repo, pats=[], opts={}, node=None, head='', badmatch=None |
|
139 | def walk(repo, pats=[], opts={}, node=None, head='', badmatch=None, | |
140 | files, matchfn, anypats = matchpats(repo, pats, opts, head) |
|
140 | globbed=False): | |
|
141 | files, matchfn, anypats = matchpats(repo, pats, opts, head, | |||
|
142 | globbed=globbed) | |||
141 | exact = dict.fromkeys(files) |
|
143 | exact = dict.fromkeys(files) | |
142 | for src, fn in repo.walk(node=node, files=files, match=matchfn, |
|
144 | for src, fn in repo.walk(node=node, files=files, match=matchfn, | |
143 | badmatch=badmatch): |
|
145 | badmatch=badmatch): |
@@ -604,7 +604,7 b' def docopy(ui, repo, pats, opts, wlock):' | |||||
604 | return res |
|
604 | return res | |
605 |
|
605 | |||
606 |
|
606 | |||
607 |
pats = |
|
607 | pats = util.expand_glob(pats) | |
608 | if not pats: |
|
608 | if not pats: | |
609 | raise util.Abort(_('no source or destination specified')) |
|
609 | raise util.Abort(_('no source or destination specified')) | |
610 | if len(pats) == 1: |
|
610 | if len(pats) == 1: | |
@@ -621,7 +621,8 b' def docopy(ui, repo, pats, opts, wlock):' | |||||
621 | copylist = [] |
|
621 | copylist = [] | |
622 | for pat in pats: |
|
622 | for pat in pats: | |
623 | srcs = [] |
|
623 | srcs = [] | |
624 |
for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts |
|
624 | for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts, | |
|
625 | globbed=True): | |||
625 | origsrc = okaytocopy(abssrc, relsrc, exact) |
|
626 | origsrc = okaytocopy(abssrc, relsrc, exact) | |
626 | if origsrc: |
|
627 | if origsrc: | |
627 | srcs.append((origsrc, abssrc, relsrc, exact)) |
|
628 | srcs.append((origsrc, abssrc, relsrc, exact)) | |
@@ -769,10 +770,16 b' def debugstate(ui, repo):' | |||||
769 | keys = dc.keys() |
|
770 | keys = dc.keys() | |
770 | keys.sort() |
|
771 | keys.sort() | |
771 | for file_ in keys: |
|
772 | for file_ in keys: | |
|
773 | if dc[file_][3] == -1: | |||
|
774 | # Pad or slice to locale representation | |||
|
775 | locale_len = len(time.strftime("%x %X", time.localtime(0))) | |||
|
776 | timestr = 'unset' | |||
|
777 | timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr)) | |||
|
778 | else: | |||
|
779 | timestr = time.strftime("%x %X", time.localtime(dc[file_][3])) | |||
772 | ui.write("%c %3o %10d %s %s\n" |
|
780 | ui.write("%c %3o %10d %s %s\n" | |
773 | % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2], |
|
781 | % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2], | |
774 |
time |
|
782 | timestr, file_)) | |
775 | time.localtime(dc[file_][3])), file_)) |
|
|||
776 | for f in repo.dirstate.copies(): |
|
783 | for f in repo.dirstate.copies(): | |
777 | ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f)) |
|
784 | ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f)) | |
778 |
|
785 | |||
@@ -2478,7 +2485,11 b' def unbundle(ui, repo, fname, **opts):' | |||||
2478 | Apply a compressed changegroup file generated by the bundle |
|
2485 | Apply a compressed changegroup file generated by the bundle | |
2479 | command. |
|
2486 | command. | |
2480 | """ |
|
2487 | """ | |
2481 | gen = changegroup.readbundle(urllib.urlopen(fname), fname) |
|
2488 | if os.path.exists(fname): | |
|
2489 | f = open(fname) | |||
|
2490 | else: | |||
|
2491 | f = urllib.urlopen(fname) | |||
|
2492 | gen = changegroup.readbundle(f, fname) | |||
2482 | modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname) |
|
2493 | modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname) | |
2483 | return postincoming(ui, repo, modheads, opts['update']) |
|
2494 | return postincoming(ui, repo, modheads, opts['update']) | |
2484 |
|
2495 |
@@ -616,6 +616,24 b' class localrepository(repo.repository):' | |||||
616 | meta = {} |
|
616 | meta = {} | |
617 | cp = self.dirstate.copied(fn) |
|
617 | cp = self.dirstate.copied(fn) | |
618 | if cp: |
|
618 | if cp: | |
|
619 | # Mark the new revision of this file as a copy of another | |||
|
620 | # file. This copy data will effectively act as a parent | |||
|
621 | # of this new revision. If this is a merge, the first | |||
|
622 | # parent will be the nullid (meaning "look up the copy data") | |||
|
623 | # and the second one will be the other parent. For example: | |||
|
624 | # | |||
|
625 | # 0 --- 1 --- 3 rev1 changes file foo | |||
|
626 | # \ / rev2 renames foo to bar and changes it | |||
|
627 | # \- 2 -/ rev3 should have bar with all changes and | |||
|
628 | # should record that bar descends from | |||
|
629 | # bar in rev2 and foo in rev1 | |||
|
630 | # | |||
|
631 | # this allows this merge to succeed: | |||
|
632 | # | |||
|
633 | # 0 --- 1 --- 3 rev4 reverts the content change from rev2 | |||
|
634 | # \ / merging rev3 and rev4 should use bar@rev2 | |||
|
635 | # \- 2 --- 4 as the merge base | |||
|
636 | # | |||
619 | meta["copy"] = cp |
|
637 | meta["copy"] = cp | |
620 | if not manifest2: # not a branch merge |
|
638 | if not manifest2: # not a branch merge | |
621 | meta["copyrev"] = hex(manifest1.get(cp, nullid)) |
|
639 | meta["copyrev"] = hex(manifest1.get(cp, nullid)) | |
@@ -624,7 +642,7 b' class localrepository(repo.repository):' | |||||
624 | meta["copyrev"] = hex(manifest1.get(cp, nullid)) |
|
642 | meta["copyrev"] = hex(manifest1.get(cp, nullid)) | |
625 | elif fp1 != nullid: # copied on local side, reversed |
|
643 | elif fp1 != nullid: # copied on local side, reversed | |
626 | meta["copyrev"] = hex(manifest2.get(cp)) |
|
644 | meta["copyrev"] = hex(manifest2.get(cp)) | |
627 |
fp2 = |
|
645 | fp2 = fp1 | |
628 | else: # directory rename |
|
646 | else: # directory rename | |
629 | meta["copyrev"] = hex(manifest1.get(cp, nullid)) |
|
647 | meta["copyrev"] = hex(manifest1.get(cp, nullid)) | |
630 | self.ui.debug(_(" %s: copy %s:%s\n") % |
|
648 | self.ui.debug(_(" %s: copy %s:%s\n") % |
@@ -14,10 +14,13 b' platform-specific details from the core.' | |||||
14 |
|
14 | |||
15 | from i18n import _ |
|
15 | from i18n import _ | |
16 | import cStringIO, errno, getpass, popen2, re, shutil, sys, tempfile |
|
16 | import cStringIO, errno, getpass, popen2, re, shutil, sys, tempfile | |
17 | import os, threading, time, calendar, ConfigParser, locale |
|
17 | import os, threading, time, calendar, ConfigParser, locale, glob | |
18 |
|
18 | |||
19 | _encoding = os.environ.get("HGENCODING") or locale.getpreferredencoding() \ |
|
19 | try: | |
20 | or "ascii" |
|
20 | _encoding = os.environ.get("HGENCODING") or locale.getpreferredencoding() \ | |
|
21 | or "ascii" | |||
|
22 | except locale.Error: | |||
|
23 | _encoding = 'ascii' | |||
21 | _encodingmode = os.environ.get("HGENCODINGMODE", "strict") |
|
24 | _encodingmode = os.environ.get("HGENCODINGMODE", "strict") | |
22 | _fallbackencoding = 'ISO-8859-1' |
|
25 | _fallbackencoding = 'ISO-8859-1' | |
23 |
|
26 | |||
@@ -233,6 +236,22 b' class UnexpectedOutput(Abort):' | |||||
233 | def always(fn): return True |
|
236 | def always(fn): return True | |
234 | def never(fn): return False |
|
237 | def never(fn): return False | |
235 |
|
238 | |||
|
239 | def expand_glob(pats): | |||
|
240 | '''On Windows, expand the implicit globs in a list of patterns''' | |||
|
241 | if os.name != 'nt': | |||
|
242 | return list(pats) | |||
|
243 | ret = [] | |||
|
244 | for p in pats: | |||
|
245 | kind, name = patkind(p, None) | |||
|
246 | if kind is None: | |||
|
247 | globbed = glob.glob(name) | |||
|
248 | if globbed: | |||
|
249 | ret.extend(globbed) | |||
|
250 | continue | |||
|
251 | # if we couldn't expand the glob, just keep it around | |||
|
252 | ret.append(p) | |||
|
253 | return ret | |||
|
254 | ||||
236 | def patkind(name, dflt_pat='glob'): |
|
255 | def patkind(name, dflt_pat='glob'): | |
237 | """Split a string into an optional pattern kind prefix and the |
|
256 | """Split a string into an optional pattern kind prefix and the | |
238 | actual pattern.""" |
|
257 | actual pattern.""" | |
@@ -358,12 +377,11 b' def canonpath(root, cwd, myname):' | |||||
358 | def matcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None): |
|
377 | def matcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None): | |
359 | return _matcher(canonroot, cwd, names, inc, exc, head, 'glob', src) |
|
378 | return _matcher(canonroot, cwd, names, inc, exc, head, 'glob', src) | |
360 |
|
379 | |||
361 |
def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', |
|
380 | def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', | |
362 | if os.name == 'nt': |
|
381 | src=None, globbed=False): | |
363 | dflt_pat = 'glob' |
|
382 | if not globbed: | |
364 | else: |
|
383 | names = expand_glob(names) | |
365 | dflt_pat = 'relpath' |
|
384 | return _matcher(canonroot, cwd, names, inc, exc, head, 'relpath', src) | |
366 | return _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src) |
|
|||
367 |
|
385 | |||
368 | def _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src): |
|
386 | def _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src): | |
369 | """build a function to match a set of file patterns |
|
387 | """build a function to match a set of file patterns |
General Comments 0
You need to be logged in to leave comments.
Login now