##// END OF EJS Templates
Merge with crew
Bryan O'Sullivan -
r5676:9ed65758 merge default
parent child Browse files
Show More
@@ -0,0 +1,108 b''
1 #!/bin/sh
2
3 echo "[extensions]" >> $HGRCPATH
4 echo "mq=" >> $HGRCPATH
5 echo "[diff]" >> $HGRCPATH
6 echo "nodates=true" >> $HGRCPATH
7
8
9 catlog() {
10 cat .hg/patches/$1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
11 hg log --template "{rev}: {desc} - {author}\n"
12 }
13
14
15 echo ==== init
16 hg init a
17 cd a
18 hg qinit
19
20
21 echo ==== qnew -U
22 hg qnew -U 1.patch
23 catlog 1
24
25 echo ==== qref
26 echo "1" >1
27 hg add
28 hg qref
29 catlog 1
30
31 echo ==== qref -u
32 hg qref -u mary
33 catlog 1
34
35 echo ==== qnew
36 hg qnew 2.patch
37 echo "2" >2
38 hg add
39 hg qref
40 catlog 2
41
42 echo ==== qref -u
43 hg qref -u jane
44 catlog 2
45
46
47 echo ==== qnew -U -m
48 hg qnew -U -m "Three" 3.patch
49 catlog 3
50
51 echo ==== qref
52 echo "3" >3
53 hg add
54 hg qref
55 catlog 3
56
57 echo ==== qref -m
58 hg qref -m "Drei"
59 catlog 3
60
61 echo ==== qref -u
62 hg qref -u mary
63 catlog 3
64
65 echo ==== qref -u -m
66 hg qref -u maria -m "Three (again)"
67 catlog 3
68
69 echo ==== qnew -m
70 hg qnew -m "Four" 4.patch
71 echo "4" >4
72 hg add
73 hg qref
74 catlog 4
75
76 echo ==== qref -u
77 hg qref -u jane
78 catlog 4
79
80
81 echo ==== qnew with HG header
82 hg qnew 5.patch
83 hg qpop
84 echo "# HG changeset patch" >>.hg/patches/5.patch
85 echo "# User johndoe" >>.hg/patches/5.patch
86 # Drop patch specific error line
87 hg qpush 2>&1 | grep -v garbage
88 catlog 5
89
90 echo ==== hg qref
91 echo "5" >5
92 hg add
93 hg qref
94 catlog 5
95
96 echo ==== hg qref -U
97 hg qref -U
98 catlog 5
99
100 echo ==== hg qref -u
101 hg qref -u johndeere
102 catlog 5
103
104
105 echo ==== "qpop -a / qpush -a"
106 hg qpop -a
107 hg qpush -a
108 hg log --template "{rev}: {desc} - {author}\n"
@@ -0,0 +1,200 b''
1 ==== init
2 ==== qnew -U
3 From: test
4
5 0: [mq]: 1.patch - test
6 ==== qref
7 adding 1
8 From: test
9
10 diff -r ... 1
11 --- /dev/null
12 +++ b/1
13 @@ -0,0 +1,1 @@
14 +1
15 0: [mq]: 1.patch - test
16 ==== qref -u
17 From: mary
18
19 diff -r ... 1
20 --- /dev/null
21 +++ b/1
22 @@ -0,0 +1,1 @@
23 +1
24 0: [mq]: 1.patch - mary
25 ==== qnew
26 adding 2
27 diff -r ... 2
28 --- /dev/null
29 +++ b/2
30 @@ -0,0 +1,1 @@
31 +2
32 1: [mq]: 2.patch - test
33 0: [mq]: 1.patch - mary
34 ==== qref -u
35 From: jane
36
37
38 diff -r ... 2
39 --- /dev/null
40 +++ b/2
41 @@ -0,0 +1,1 @@
42 +2
43 1: [mq]: 2.patch - jane
44 0: [mq]: 1.patch - mary
45 ==== qnew -U -m
46 From: test
47
48 Three
49 2: Three - test
50 1: [mq]: 2.patch - jane
51 0: [mq]: 1.patch - mary
52 ==== qref
53 adding 3
54 From: test
55
56 Three
57
58 diff -r ... 3
59 --- /dev/null
60 +++ b/3
61 @@ -0,0 +1,1 @@
62 +3
63 2: Three - test
64 1: [mq]: 2.patch - jane
65 0: [mq]: 1.patch - mary
66 ==== qref -m
67 From: test
68
69 Drei
70
71 diff -r ... 3
72 --- /dev/null
73 +++ b/3
74 @@ -0,0 +1,1 @@
75 +3
76 2: Drei - test
77 1: [mq]: 2.patch - jane
78 0: [mq]: 1.patch - mary
79 ==== qref -u
80 From: mary
81
82 Drei
83
84 diff -r ... 3
85 --- /dev/null
86 +++ b/3
87 @@ -0,0 +1,1 @@
88 +3
89 2: Drei - mary
90 1: [mq]: 2.patch - jane
91 0: [mq]: 1.patch - mary
92 ==== qref -u -m
93 From: maria
94
95 Three (again)
96
97 diff -r ... 3
98 --- /dev/null
99 +++ b/3
100 @@ -0,0 +1,1 @@
101 +3
102 2: Three (again) - maria
103 1: [mq]: 2.patch - jane
104 0: [mq]: 1.patch - mary
105 ==== qnew -m
106 adding 4
107 Four
108
109 diff -r ... 4
110 --- /dev/null
111 +++ b/4
112 @@ -0,0 +1,1 @@
113 +4
114 3: Four - test
115 2: Three (again) - maria
116 1: [mq]: 2.patch - jane
117 0: [mq]: 1.patch - mary
118 ==== qref -u
119 From: jane
120
121 Four
122
123 diff -r ... 4
124 --- /dev/null
125 +++ b/4
126 @@ -0,0 +1,1 @@
127 +4
128 3: Four - jane
129 2: Three (again) - maria
130 1: [mq]: 2.patch - jane
131 0: [mq]: 1.patch - mary
132 ==== qnew with HG header
133 Now at: 4.patch
134 applying 5.patch
135 patch failed, unable to continue (try -v)
136 patch 5.patch is empty
137 Now at: 5.patch
138 # HG changeset patch
139 # User johndoe
140 4: imported patch 5.patch - johndoe
141 3: Four - jane
142 2: Three (again) - maria
143 1: [mq]: 2.patch - jane
144 0: [mq]: 1.patch - mary
145 ==== hg qref
146 adding 5
147 # HG changeset patch
148 # User johndoe
149
150 diff -r ... 5
151 --- /dev/null
152 +++ b/5
153 @@ -0,0 +1,1 @@
154 +5
155 4: [mq]: 5.patch - johndoe
156 3: Four - jane
157 2: Three (again) - maria
158 1: [mq]: 2.patch - jane
159 0: [mq]: 1.patch - mary
160 ==== hg qref -U
161 # HG changeset patch
162 # User test
163
164 diff -r ... 5
165 --- /dev/null
166 +++ b/5
167 @@ -0,0 +1,1 @@
168 +5
169 4: [mq]: 5.patch - test
170 3: Four - jane
171 2: Three (again) - maria
172 1: [mq]: 2.patch - jane
173 0: [mq]: 1.patch - mary
174 ==== hg qref -u
175 # HG changeset patch
176 # User johndeere
177
178 diff -r ... 5
179 --- /dev/null
180 +++ b/5
181 @@ -0,0 +1,1 @@
182 +5
183 4: [mq]: 5.patch - johndeere
184 3: Four - jane
185 2: Three (again) - maria
186 1: [mq]: 2.patch - jane
187 0: [mq]: 1.patch - mary
188 ==== qpop -a / qpush -a
189 Patch queue now empty
190 applying 1.patch
191 applying 2.patch
192 applying 3.patch
193 applying 4.patch
194 applying 5.patch
195 Now at: 5.patch
196 4: imported patch 5.patch - johndeere
197 3: Four - jane
198 2: Three (again) - maria
199 1: imported patch 2.patch - jane
200 0: imported patch 1.patch - mary
@@ -281,7 +281,7 b' hooks::'
281 281 commit to proceed. Non-zero status will cause the commit to fail.
282 282 Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
283 283 preoutgoing;;
284 Run before computing changes to send from the local repository to
284 Run before collecting changes to send from the local repository to
285 285 another. Non-zero status will cause failure. This lets you
286 286 prevent pull over http or ssh. Also prevents against local pull,
287 287 push (outbound) or bundle commands, but not effective, since you
@@ -603,6 +603,7 b' class queue:'
603 603 def new(self, repo, patch, *pats, **opts):
604 604 msg = opts.get('msg')
605 605 force = opts.get('force')
606 user = opts.get('user')
606 607 if os.path.exists(self.join(patch)):
607 608 raise util.Abort(_('patch "%s" already exists') % patch)
608 609 if opts.get('include') or opts.get('exclude') or pats:
@@ -617,7 +618,7 b' class queue:'
617 618 try:
618 619 insert = self.full_series_end()
619 620 commitmsg = msg and msg or ("[mq]: %s" % patch)
620 n = repo.commit(commitfiles, commitmsg, match=match, force=True)
621 n = repo.commit(commitfiles, commitmsg, user, match=match, force=True)
621 622 if n == None:
622 623 raise util.Abort(_("repo commit failed"))
623 624 self.full_series[insert:insert] = [patch]
@@ -626,6 +627,8 b' class queue:'
626 627 self.series_dirty = 1
627 628 self.applied_dirty = 1
628 629 p = self.opener(patch, "w")
630 if user:
631 p.write("From: " + user + "\n\n")
629 632 if msg:
630 633 msg = msg + "\n"
631 634 p.write(msg)
@@ -945,6 +948,22 b' class queue:'
945 948 while message[mi] != comments[ci]:
946 949 ci += 1
947 950 del comments[ci]
951
952 newuser = opts.get('user')
953 if newuser:
954 # Update all references to a user in the patch header.
955 # If none found, add "From: " header.
956 needfrom = True
957 for prefix in ['# User ', 'From: ']:
958 for i in xrange(len(comments)):
959 if comments[i].startswith(prefix):
960 comments[i] = prefix + newuser
961 needfrom = False
962 break
963 if needfrom:
964 comments = ['From: ' + newuser, ''] + comments
965 user = newuser
966
948 967 if msg:
949 968 comments.append(msg)
950 969
@@ -1070,9 +1089,12 b' class queue:'
1070 1089 else:
1071 1090 message = msg
1072 1091
1092 if not user:
1093 user = changes[1]
1094
1073 1095 self.strip(repo, top, update=False,
1074 1096 backup='strip')
1075 n = repo.commit(filelist, message, changes[1], match=matchfn,
1097 n = repo.commit(filelist, message, user, match=matchfn,
1076 1098 force=1)
1077 1099 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
1078 1100 self.applied_dirty = 1
@@ -1605,6 +1627,12 b' def prev(ui, repo, **opts):'
1605 1627 return q.qseries(repo, start=l-2, length=1, status='A',
1606 1628 summary=opts.get('summary'))
1607 1629
1630 def setupheaderopts(ui, opts):
1631 def do(opt,val):
1632 if not opts[opt] and opts['current' + opt]:
1633 opts[opt] = val
1634 do('user', ui.username())
1635
1608 1636 def new(ui, repo, patch, *args, **opts):
1609 1637 """create a new patch
1610 1638
@@ -1623,6 +1651,7 b' def new(ui, repo, patch, *args, **opts):'
1623 1651 if opts['edit']:
1624 1652 message = ui.edit(message, ui.username())
1625 1653 opts['msg'] = message
1654 setupheaderopts(ui, opts)
1626 1655 q.new(repo, patch, *args, **opts)
1627 1656 q.save_dirty()
1628 1657 return 0
@@ -1648,6 +1677,7 b' def refresh(ui, repo, *pats, **opts):'
1648 1677 patch = q.applied[-1].name
1649 1678 (message, comment, user, date, hasdiff) = q.readheaders(patch)
1650 1679 message = ui.edit('\n'.join(message), user or ui.username())
1680 setupheaderopts(ui, opts)
1651 1681 ret = q.refresh(repo, pats, msg=message, **opts)
1652 1682 q.save_dirty()
1653 1683 return ret
@@ -2138,6 +2168,10 b' def reposetup(ui, repo):'
2138 2168
2139 2169 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
2140 2170
2171 headeropts = [
2172 ('U', 'currentuser', None, _('add "From: <current user>" to patch')),
2173 ('u', 'user', '', _('add "From: <given user>" to patch'))]
2174
2141 2175 cmdtable = {
2142 2176 "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')),
2143 2177 "qclone":
@@ -2196,7 +2230,7 b' cmdtable = {'
2196 2230 [('e', 'edit', None, _('edit commit message')),
2197 2231 ('f', 'force', None, _('import uncommitted changes into patch')),
2198 2232 ('g', 'git', None, _('use git extended diff format')),
2199 ] + commands.walkopts + commands.commitopts,
2233 ] + commands.walkopts + commands.commitopts + headeropts,
2200 2234 _('hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...')),
2201 2235 "qnext": (next, [] + seriesopts, _('hg qnext [-s]')),
2202 2236 "qprev": (prev, [] + seriesopts, _('hg qprev [-s]')),
@@ -2219,7 +2253,7 b' cmdtable = {'
2219 2253 [('e', 'edit', None, _('edit commit message')),
2220 2254 ('g', 'git', None, _('use git extended diff format')),
2221 2255 ('s', 'short', None, _('refresh only files already in the patch')),
2222 ] + commands.walkopts + commands.commitopts,
2256 ] + commands.walkopts + commands.commitopts + headeropts,
2223 2257 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')),
2224 2258 'qrename|qmv':
2225 2259 (rename, [], _('hg qrename PATCH1 [PATCH2]')),
@@ -2029,6 +2029,7 b' def remove(ui, repo, *pats, **opts):'
2029 2029 forget.append(abs)
2030 2030 continue
2031 2031 reason = _('has been marked for add (use -f to force removal)')
2032 exact = 1 # force the message
2032 2033 elif abs not in repo.dirstate:
2033 2034 reason = _('is not managed')
2034 2035 elif opts['after'] and not exact and abs not in deleted:
@@ -67,7 +67,7 b' class _demandmod(object):'
67 67 return "<proxied module '%s'>" % self._data[0]
68 68 return "<unloaded module '%s'>" % self._data[0]
69 69 def __call__(self, *args, **kwargs):
70 raise TypeError("'unloaded module' object is not callable")
70 raise TypeError("%s object is not callable" % repr(self))
71 71 def __getattribute__(self, attr):
72 72 if attr in ('_data', '_extend', '_load', '_module'):
73 73 return object.__getattribute__(self, attr)
@@ -133,6 +133,8 b' def _runcatch(ui, args):'
133 133
134 134 except util.Abort, inst:
135 135 ui.warn(_("abort: %s\n") % inst)
136 except MemoryError:
137 ui.warn(_("abort: out of memory\n"))
136 138 except SystemExit, inst:
137 139 # Commands shouldn't sys.exit directly, but give a return code.
138 140 # Just in case catch this and and pass exit code to caller.
@@ -1,35 +1,74 b''
1 1 import getopt
2 2
3 3 def fancyopts(args, options, state):
4 long = []
5 short = ''
6 map = {}
7 dt = {}
4 """
5 read args, parse options, and store options in state
6
7 each option is a tuple of:
8
9 short option or ''
10 long option
11 default value
12 description
13
14 option types include:
15
16 boolean or none - option sets variable in state to true
17 string - parameter string is stored in state
18 list - parameter string is added to a list
19 integer - parameter strings is stored as int
20 function - call function with parameter
8 21
9 for s, l, d, c in options:
10 pl = l.replace('-', '_')
11 map['-'+s] = map['--'+l] = pl
12 if isinstance(d, list):
13 state[pl] = d[:]
22 non-option args are returned
23 """
24 namelist = []
25 shortlist = ''
26 argmap = {}
27 defmap = {}
28
29 for short, name, default, comment in options:
30 # convert opts to getopt format
31 oname = name
32 name = name.replace('-', '_')
33
34 argmap['-' + short] = argmap['--' + oname] = name
35 defmap[name] = default
36
37 # copy defaults to state
38 if isinstance(default, list):
39 state[name] = default[:]
40 elif callable(default):
41 print "whoa", name, default
42 state[name] = None
14 43 else:
15 state[pl] = d
16 dt[pl] = type(d)
17 if (d is not None and d is not True and d is not False and
18 not callable(d)):
19 if s: s += ':'
20 if l: l += '='
21 if s: short = short + s
22 if l: long.append(l)
44 state[name] = default
23 45
24 opts, args = getopt.getopt(args, short, long)
46 # does it take a parameter?
47 if not (default is None or default is True or default is False):
48 if short: short += ':'
49 if oname: oname += '='
50 if short:
51 shortlist += short
52 if name:
53 namelist.append(oname)
54
55 # parse arguments
56 opts, args = getopt.getopt(args, shortlist, namelist)
25 57
26 for opt, arg in opts:
27 if dt[map[opt]] is type(fancyopts): state[map[opt]](state, map[opt], arg)
28 elif dt[map[opt]] is type(1): state[map[opt]] = int(arg)
29 elif dt[map[opt]] is type(''): state[map[opt]] = arg
30 elif dt[map[opt]] is type([]): state[map[opt]].append(arg)
31 elif dt[map[opt]] is type(None): state[map[opt]] = True
32 elif dt[map[opt]] is type(False): state[map[opt]] = True
58 # transfer result to state
59 for opt, val in opts:
60 name = argmap[opt]
61 t = type(defmap[name])
62 if t is type(fancyopts):
63 state[name] = defmap[name](val)
64 elif t is type(1):
65 state[name] = int(val)
66 elif t is type(''):
67 state[name] = val
68 elif t is type([]):
69 state[name].append(val)
70 elif t is type(None) or t is type(False):
71 state[name] = True
33 72
73 # return unparsed args
34 74 return args
35
@@ -280,13 +280,13 b' def update(repo, node):'
280 280 # len(pl)==1, otherwise _merge.update() would have raised util.Abort:
281 281 repo.ui.status(_(" hg update %s\n hg update %s\n")
282 282 % (pl[0].rev(), repo.changectx(node).rev()))
283 return stats[3]
283 return stats[3] > 0
284 284
285 285 def clean(repo, node, show_stats=True):
286 286 """forcibly switch the working directory to node, clobbering changes"""
287 287 stats = _merge.update(repo, node, False, True, None)
288 288 if show_stats: _showstats(repo, stats)
289 return stats[3]
289 return stats[3] > 0
290 290
291 291 def merge(repo, node, force=None, remind=True):
292 292 """branch merge with node, resolving changes"""
@@ -301,11 +301,11 b' def merge(repo, node, force=None, remind'
301 301 % (pl[0].rev(), pl[1].rev()))
302 302 elif remind:
303 303 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
304 return stats[3]
304 return stats[3] > 0
305 305
306 306 def revert(repo, node, choose):
307 307 """revert changes to revision in node without updating dirstate"""
308 return _merge.update(repo, node, False, True, choose)[3]
308 return _merge.update(repo, node, False, True, choose)[3] > 0
309 309
310 310 def verify(repo):
311 311 """verify the consistency of a repository"""
@@ -6,18 +6,21 b''
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from i18n import _
9 import util
9 import util, re
10
11 _commentre = None
10 12
11 13 def _parselines(fp):
12 14 for line in fp:
13 if not line.endswith('\n'):
14 line += '\n'
15 escape = False
16 for i in xrange(len(line)):
17 if escape: escape = False
18 elif line[i] == '\\': escape = True
19 elif line[i] == '#': break
20 line = line[:i].rstrip()
15 if "#" in line:
16 global _commentre
17 if not _commentre:
18 _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
19 # remove comments prefixed by an even number of escapes
20 line = _commentre.sub(r'\1', line)
21 # fixup properly escaped comments that survived the above
22 line = line.replace("\\#", "#")
23 line = line.rstrip()
21 24 if line:
22 25 yield line
23 26
@@ -661,6 +661,7 b' class localrepository(repo.repository):'
661 661 match=util.always, force=False, force_editor=False,
662 662 p1=None, p2=None, extra={}, empty_ok=False):
663 663 wlock = lock = tr = None
664 valid = 0 # don't save the dirstate if this isn't set
664 665 try:
665 666 commit = []
666 667 remove = []
@@ -747,6 +748,9 b' class localrepository(repo.repository):'
747 748 if old_exec != new_exec or old_link != new_link:
748 749 changed.append(f)
749 750 m1.set(f, new_exec, new_link)
751 if use_dirstate:
752 self.dirstate.normal(f)
753
750 754 except (OSError, IOError):
751 755 if use_dirstate:
752 756 self.ui.warn(_("trouble committing %s!\n") % f)
@@ -817,14 +821,15 b' class localrepository(repo.repository):'
817 821 if use_dirstate or update_dirstate:
818 822 self.dirstate.setparents(n)
819 823 if use_dirstate:
820 for f in new:
821 self.dirstate.normal(f)
822 824 for f in removed:
823 825 self.dirstate.forget(f)
826 valid = 1 # our dirstate updates are complete
824 827
825 828 self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2)
826 829 return n
827 830 finally:
831 if not valid: # don't save our updated dirstate
832 self.dirstate.invalidate()
828 833 del tr, lock, wlock
829 834
830 835 def walk(self, node=None, files=[], match=util.always, badmatch=None):
@@ -302,24 +302,26 b" unidesc = re.compile('@@ -(\\d+)(,(\\d+))?"
302 302 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
303 303
304 304 class patchfile:
305 def __init__(self, ui, fname):
305 def __init__(self, ui, fname, missing=False):
306 306 self.fname = fname
307 307 self.ui = ui
308 try:
309 fp = file(fname, 'rb')
310 self.lines = fp.readlines()
311 self.exists = True
312 except IOError:
308 self.lines = []
309 self.exists = False
310 self.missing = missing
311 if not missing:
312 try:
313 fp = file(fname, 'rb')
314 self.lines = fp.readlines()
315 self.exists = True
316 except IOError:
317 pass
318 else:
319 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
320
321 if not self.exists:
313 322 dirname = os.path.dirname(fname)
314 323 if dirname and not os.path.isdir(dirname):
315 dirs = dirname.split(os.path.sep)
316 d = ""
317 for x in dirs:
318 d = os.path.join(d, x)
319 if not os.path.isdir(d):
320 os.mkdir(d)
321 self.lines = []
322 self.exists = False
324 os.makedirs(dirname)
323 325
324 326 self.hash = {}
325 327 self.dirty = 0
@@ -427,6 +429,10 b' class patchfile:'
427 429 if reverse:
428 430 h.reverse()
429 431
432 if self.missing:
433 self.rej.append(h)
434 return -1
435
430 436 if self.exists and h.createfile():
431 437 self.ui.warn(_("file %s already exists\n") % self.fname)
432 438 self.rej.append(h)
@@ -796,31 +802,32 b' def selectfile(afile_orig, bfile_orig, h'
796 802 nulla = afile_orig == "/dev/null"
797 803 nullb = bfile_orig == "/dev/null"
798 804 afile = pathstrip(afile_orig, strip)
799 gooda = os.path.exists(afile) and not nulla
805 gooda = not nulla and os.path.exists(afile)
800 806 bfile = pathstrip(bfile_orig, strip)
801 807 if afile == bfile:
802 808 goodb = gooda
803 809 else:
804 goodb = os.path.exists(bfile) and not nullb
810 goodb = not nullb and os.path.exists(bfile)
805 811 createfunc = hunk.createfile
806 812 if reverse:
807 813 createfunc = hunk.rmfile
808 if not goodb and not gooda and not createfunc():
809 raise PatchError(_("unable to find %s or %s for patching") %
810 (afile, bfile))
811 if gooda and goodb:
812 fname = bfile
813 if afile in bfile:
814 missing = not goodb and not gooda and not createfunc()
815 fname = None
816 if not missing:
817 if gooda and goodb:
818 fname = (afile in bfile) and afile or bfile
819 elif gooda:
814 820 fname = afile
815 elif gooda:
816 fname = afile
817 elif not nullb:
818 fname = bfile
819 if afile in bfile:
821
822 if not fname:
823 if not nullb:
824 fname = (afile in bfile) and afile or bfile
825 elif not nulla:
820 826 fname = afile
821 elif not nulla:
822 fname = afile
823 return fname
827 else:
828 raise PatchError(_("undefined source and destination files"))
829
830 return fname, missing
824 831
825 832 class linereader:
826 833 # simple class to allow pushing lines back into the input stream
@@ -838,14 +845,16 b' class linereader:'
838 845 return l
839 846 return self.fp.readline()
840 847
841 def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False,
842 rejmerge=None, updatedir=None):
843 """reads a patch from fp and tries to apply it. The dict 'changed' is
844 filled in with all of the filenames changed by the patch. Returns 0
845 for a clean patch, -1 if any rejects were found and 1 if there was
846 any fuzz."""
848 def iterhunks(ui, fp, sourcefile=None):
849 """Read a patch and yield the following events:
850 - ("file", afile, bfile, firsthunk): select a new target file.
851 - ("hunk", hunk): a new hunk is ready to be applied, follows a
852 "file" event.
853 - ("git", gitchanges): current diff is in git format, gitchanges
854 maps filenames to gitpatch records. Unique event.
855 """
847 856
848 def scangitpatch(fp, firstline, cwd=None):
857 def scangitpatch(fp, firstline):
849 858 '''git patches can modify a file, then copy that file to
850 859 a new file, but expect the source to be the unmodified form.
851 860 So we scan the patch looking for that case so we can do
@@ -858,46 +867,28 b' def applydiff(ui, fp, changed, strip=1, '
858 867 fp = cStringIO.StringIO(fp.read())
859 868
860 869 (dopatch, gitpatches) = readgitpatch(fp, firstline)
861 for gp in gitpatches:
862 if gp.op in ('COPY', 'RENAME'):
863 copyfile(gp.oldpath, gp.path, basedir=cwd)
864
865 870 fp.seek(pos)
866 871
867 872 return fp, dopatch, gitpatches
868 873
874 changed = {}
869 875 current_hunk = None
870 current_file = None
871 876 afile = ""
872 877 bfile = ""
873 878 state = None
874 879 hunknum = 0
875 rejects = 0
880 emitfile = False
876 881
877 882 git = False
878 883 gitre = re.compile('diff --git (a/.*) (b/.*)')
879 884
880 885 # our states
881 886 BFILE = 1
882 err = 0
883 887 context = None
884 888 lr = linereader(fp)
885 889 dopatch = True
886 890 gitworkdone = False
887 891
888 def getpatchfile(afile, bfile, hunk):
889 try:
890 if sourcefile:
891 targetfile = patchfile(ui, sourcefile)
892 else:
893 targetfile = selectfile(afile, bfile, hunk,
894 strip, reverse)
895 targetfile = patchfile(ui, targetfile)
896 return targetfile
897 except PatchError, err:
898 ui.warn(str(err) + '\n')
899 return None
900
901 892 while True:
902 893 newfile = False
903 894 x = lr.readline()
@@ -906,11 +897,7 b' def applydiff(ui, fp, changed, strip=1, '
906 897 if current_hunk:
907 898 if x.startswith('\ '):
908 899 current_hunk.fix_newline()
909 ret = current_file.apply(current_hunk, reverse)
910 if ret >= 0:
911 changed.setdefault(current_file.fname, (None, None))
912 if ret > 0:
913 err = 1
900 yield 'hunk', current_hunk
914 901 current_hunk = None
915 902 gitworkdone = False
916 903 if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or
@@ -924,21 +911,15 b' def applydiff(ui, fp, changed, strip=1, '
924 911 current_hunk = None
925 912 continue
926 913 hunknum += 1
927 if not current_file:
928 current_file = getpatchfile(afile, bfile, current_hunk)
929 if not current_file:
930 current_file, current_hunk = None, None
931 rejects += 1
932 continue
914 if emitfile:
915 emitfile = False
916 yield 'file', (afile, bfile, current_hunk)
933 917 elif state == BFILE and x.startswith('GIT binary patch'):
934 918 current_hunk = binhunk(changed[bfile[2:]][1])
935 919 hunknum += 1
936 if not current_file:
937 current_file = getpatchfile(afile, bfile, current_hunk)
938 if not current_file:
939 current_file, current_hunk = None, None
940 rejects += 1
941 continue
920 if emitfile:
921 emitfile = False
922 yield 'file', (afile, bfile, current_hunk)
942 923 current_hunk.extract(fp)
943 924 elif x.startswith('diff --git'):
944 925 # check for git diff, scanning the whole patch file if needed
@@ -948,6 +929,7 b' def applydiff(ui, fp, changed, strip=1, '
948 929 if not git:
949 930 git = True
950 931 fp, dopatch, gitpatches = scangitpatch(fp, x)
932 yield 'git', gitpatches
951 933 for gp in gitpatches:
952 934 changed[gp.path] = (gp.op, gp)
953 935 # else error?
@@ -984,36 +966,79 b' def applydiff(ui, fp, changed, strip=1, '
984 966 bfile = parsefilename(l2)
985 967
986 968 if newfile:
987 if current_file:
988 current_file.close()
989 if rejmerge:
990 rejmerge(current_file)
991 rejects += len(current_file.rej)
969 emitfile = True
992 970 state = BFILE
993 current_file = None
994 971 hunknum = 0
995 972 if current_hunk:
996 973 if current_hunk.complete():
974 yield 'hunk', current_hunk
975 else:
976 raise PatchError(_("malformed patch %s %s") % (afile,
977 current_hunk.desc))
978
979 if hunknum == 0 and dopatch and not gitworkdone:
980 raise NoHunks
981
982 def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False,
983 rejmerge=None, updatedir=None):
984 """reads a patch from fp and tries to apply it. The dict 'changed' is
985 filled in with all of the filenames changed by the patch. Returns 0
986 for a clean patch, -1 if any rejects were found and 1 if there was
987 any fuzz."""
988
989 rejects = 0
990 err = 0
991 current_file = None
992 gitpatches = None
993
994 def closefile():
995 if not current_file:
996 return 0
997 current_file.close()
998 if rejmerge:
999 rejmerge(current_file)
1000 return len(current_file.rej)
1001
1002 for state, values in iterhunks(ui, fp, sourcefile):
1003 if state == 'hunk':
1004 if not current_file:
1005 continue
1006 current_hunk = values
997 1007 ret = current_file.apply(current_hunk, reverse)
998 1008 if ret >= 0:
999 1009 changed.setdefault(current_file.fname, (None, None))
1000 1010 if ret > 0:
1001 1011 err = 1
1012 elif state == 'file':
1013 rejects += closefile()
1014 afile, bfile, first_hunk = values
1015 try:
1016 if sourcefile:
1017 current_file = patchfile(ui, sourcefile)
1018 else:
1019 current_file, missing = selectfile(afile, bfile, first_hunk,
1020 strip, reverse)
1021 current_file = patchfile(ui, current_file, missing)
1022 except PatchError, err:
1023 ui.warn(str(err) + '\n')
1024 current_file, current_hunk = None, None
1025 rejects += 1
1026 continue
1027 elif state == 'git':
1028 gitpatches = values
1029 for gp in gitpatches:
1030 if gp.op in ('COPY', 'RENAME'):
1031 copyfile(gp.oldpath, gp.path)
1032 changed[gp.path] = (gp.op, gp)
1002 1033 else:
1003 fname = current_file and current_file.fname or None
1004 raise PatchError(_("malformed patch %s %s") % (fname,
1005 current_hunk.desc))
1006 if current_file:
1007 current_file.close()
1008 if rejmerge:
1009 rejmerge(current_file)
1010 rejects += len(current_file.rej)
1011 if updatedir and git:
1034 raise util.Abort(_('unsupported parser state: %s') % state)
1035
1036 rejects += closefile()
1037
1038 if updatedir and gitpatches:
1012 1039 updatedir(gitpatches)
1013 1040 if rejects:
1014 1041 return -1
1015 if hunknum == 0 and dopatch and not gitworkdone:
1016 raise NoHunks
1017 1042 return err
1018 1043
1019 1044 def diffopts(ui, opts={}, untrusted=False):
@@ -919,7 +919,15 b" if os.name == 'nt':"
919 919
920 920 def write(self, s):
921 921 try:
922 return self.fp.write(s)
922 # This is workaround for "Not enough space" error on
923 # writing large size of data to console.
924 limit = 16000
925 l = len(s)
926 start = 0
927 while start < l:
928 end = start + limit
929 self.fp.write(s[start:end])
930 start = end
923 931 except IOError, inst:
924 932 if inst.errno != 0: raise
925 933 self.close()
@@ -41,6 +41,8 b' hg qpush'
41 41 echo % display added files
42 42 cat a
43 43 cat c
44 echo % display rejections
45 cat b.rej
44 46 cd ..
45 47
46 48
@@ -65,5 +67,7 b' hg st'
65 67 echo % display added files
66 68 cat a
67 69 cat c
70 echo % display rejections
71 cat b.rej
68 72 cd ..
69 73
@@ -2,24 +2,48 b' adding b'
2 2 Patch queue now empty
3 3 % push patch with missing target
4 4 applying changeb
5 unable to find b or b for patching
6 unable to find b or b for patching
5 unable to find 'b' for patching
6 2 out of 2 hunks FAILED -- saving rejects to file b.rej
7 7 patch failed, unable to continue (try -v)
8 8 patch failed, rejects left in working dir
9 9 Errors during apply, please fix and refresh changeb
10 10 % display added files
11 11 a
12 12 c
13 % display rejections
14 --- b
15 +++ b
16 @@ -1,3 +1,5 @@ a
17 +b
18 +b
19 a
20 a
21 a
22 @@ -8,3 +10,5 @@ a
23 a
24 a
25 a
26 +c
27 +c
13 28 adding b
14 29 Patch queue now empty
15 30 % push git patch with missing target
16 31 applying changeb
17 unable to find b or b for patching
32 unable to find 'b' for patching
33 1 out of 1 hunk FAILED -- saving rejects to file b.rej
18 34 patch failed, unable to continue (try -v)
19 35 b: No such file or directory
20 36 b not tracked!
21 37 patch failed, rejects left in working dir
22 38 Errors during apply, please fix and refresh changeb
39 ? b.rej
23 40 % display added files
24 41 a
25 42 c
43 % display rejections
44 --- b
45 +++ b
46 GIT binary patch
47 literal 2
48 Jc${No0000400IC2
49
General Comments 0
You need to be logged in to leave comments. Login now