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 | commit to proceed. Non-zero status will cause the commit to fail. |
|
281 | commit to proceed. Non-zero status will cause the commit to fail. | |
282 | Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2. |
|
282 | Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2. | |
283 | preoutgoing;; |
|
283 | preoutgoing;; | |
284 |
Run before co |
|
284 | Run before collecting changes to send from the local repository to | |
285 | another. Non-zero status will cause failure. This lets you |
|
285 | another. Non-zero status will cause failure. This lets you | |
286 | prevent pull over http or ssh. Also prevents against local pull, |
|
286 | prevent pull over http or ssh. Also prevents against local pull, | |
287 | push (outbound) or bundle commands, but not effective, since you |
|
287 | push (outbound) or bundle commands, but not effective, since you |
@@ -603,6 +603,7 b' class queue:' | |||||
603 | def new(self, repo, patch, *pats, **opts): |
|
603 | def new(self, repo, patch, *pats, **opts): | |
604 | msg = opts.get('msg') |
|
604 | msg = opts.get('msg') | |
605 | force = opts.get('force') |
|
605 | force = opts.get('force') | |
|
606 | user = opts.get('user') | |||
606 | if os.path.exists(self.join(patch)): |
|
607 | if os.path.exists(self.join(patch)): | |
607 | raise util.Abort(_('patch "%s" already exists') % patch) |
|
608 | raise util.Abort(_('patch "%s" already exists') % patch) | |
608 | if opts.get('include') or opts.get('exclude') or pats: |
|
609 | if opts.get('include') or opts.get('exclude') or pats: | |
@@ -617,7 +618,7 b' class queue:' | |||||
617 | try: |
|
618 | try: | |
618 | insert = self.full_series_end() |
|
619 | insert = self.full_series_end() | |
619 | commitmsg = msg and msg or ("[mq]: %s" % patch) |
|
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 | if n == None: |
|
622 | if n == None: | |
622 | raise util.Abort(_("repo commit failed")) |
|
623 | raise util.Abort(_("repo commit failed")) | |
623 | self.full_series[insert:insert] = [patch] |
|
624 | self.full_series[insert:insert] = [patch] | |
@@ -626,6 +627,8 b' class queue:' | |||||
626 | self.series_dirty = 1 |
|
627 | self.series_dirty = 1 | |
627 | self.applied_dirty = 1 |
|
628 | self.applied_dirty = 1 | |
628 | p = self.opener(patch, "w") |
|
629 | p = self.opener(patch, "w") | |
|
630 | if user: | |||
|
631 | p.write("From: " + user + "\n\n") | |||
629 | if msg: |
|
632 | if msg: | |
630 | msg = msg + "\n" |
|
633 | msg = msg + "\n" | |
631 | p.write(msg) |
|
634 | p.write(msg) | |
@@ -945,6 +948,22 b' class queue:' | |||||
945 | while message[mi] != comments[ci]: |
|
948 | while message[mi] != comments[ci]: | |
946 | ci += 1 |
|
949 | ci += 1 | |
947 | del comments[ci] |
|
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 | if msg: |
|
967 | if msg: | |
949 | comments.append(msg) |
|
968 | comments.append(msg) | |
950 |
|
969 | |||
@@ -1070,9 +1089,12 b' class queue:' | |||||
1070 | else: |
|
1089 | else: | |
1071 | message = msg |
|
1090 | message = msg | |
1072 |
|
1091 | |||
|
1092 | if not user: | |||
|
1093 | user = changes[1] | |||
|
1094 | ||||
1073 | self.strip(repo, top, update=False, |
|
1095 | self.strip(repo, top, update=False, | |
1074 | backup='strip') |
|
1096 | backup='strip') | |
1075 |
n = repo.commit(filelist, message, |
|
1097 | n = repo.commit(filelist, message, user, match=matchfn, | |
1076 | force=1) |
|
1098 | force=1) | |
1077 | self.applied[-1] = statusentry(revlog.hex(n), patchfn) |
|
1099 | self.applied[-1] = statusentry(revlog.hex(n), patchfn) | |
1078 | self.applied_dirty = 1 |
|
1100 | self.applied_dirty = 1 | |
@@ -1605,6 +1627,12 b' def prev(ui, repo, **opts):' | |||||
1605 | return q.qseries(repo, start=l-2, length=1, status='A', |
|
1627 | return q.qseries(repo, start=l-2, length=1, status='A', | |
1606 | summary=opts.get('summary')) |
|
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 | def new(ui, repo, patch, *args, **opts): |
|
1636 | def new(ui, repo, patch, *args, **opts): | |
1609 | """create a new patch |
|
1637 | """create a new patch | |
1610 |
|
1638 | |||
@@ -1623,6 +1651,7 b' def new(ui, repo, patch, *args, **opts):' | |||||
1623 | if opts['edit']: |
|
1651 | if opts['edit']: | |
1624 | message = ui.edit(message, ui.username()) |
|
1652 | message = ui.edit(message, ui.username()) | |
1625 | opts['msg'] = message |
|
1653 | opts['msg'] = message | |
|
1654 | setupheaderopts(ui, opts) | |||
1626 | q.new(repo, patch, *args, **opts) |
|
1655 | q.new(repo, patch, *args, **opts) | |
1627 | q.save_dirty() |
|
1656 | q.save_dirty() | |
1628 | return 0 |
|
1657 | return 0 | |
@@ -1648,6 +1677,7 b' def refresh(ui, repo, *pats, **opts):' | |||||
1648 | patch = q.applied[-1].name |
|
1677 | patch = q.applied[-1].name | |
1649 | (message, comment, user, date, hasdiff) = q.readheaders(patch) |
|
1678 | (message, comment, user, date, hasdiff) = q.readheaders(patch) | |
1650 | message = ui.edit('\n'.join(message), user or ui.username()) |
|
1679 | message = ui.edit('\n'.join(message), user or ui.username()) | |
|
1680 | setupheaderopts(ui, opts) | |||
1651 | ret = q.refresh(repo, pats, msg=message, **opts) |
|
1681 | ret = q.refresh(repo, pats, msg=message, **opts) | |
1652 | q.save_dirty() |
|
1682 | q.save_dirty() | |
1653 | return ret |
|
1683 | return ret | |
@@ -2138,6 +2168,10 b' def reposetup(ui, repo):' | |||||
2138 |
|
2168 | |||
2139 | seriesopts = [('s', 'summary', None, _('print first line of patch header'))] |
|
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 | cmdtable = { |
|
2175 | cmdtable = { | |
2142 | "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')), |
|
2176 | "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')), | |
2143 | "qclone": |
|
2177 | "qclone": | |
@@ -2196,7 +2230,7 b' cmdtable = {' | |||||
2196 | [('e', 'edit', None, _('edit commit message')), |
|
2230 | [('e', 'edit', None, _('edit commit message')), | |
2197 | ('f', 'force', None, _('import uncommitted changes into patch')), |
|
2231 | ('f', 'force', None, _('import uncommitted changes into patch')), | |
2198 | ('g', 'git', None, _('use git extended diff format')), |
|
2232 | ('g', 'git', None, _('use git extended diff format')), | |
2199 | ] + commands.walkopts + commands.commitopts, |
|
2233 | ] + commands.walkopts + commands.commitopts + headeropts, | |
2200 | _('hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...')), |
|
2234 | _('hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...')), | |
2201 | "qnext": (next, [] + seriesopts, _('hg qnext [-s]')), |
|
2235 | "qnext": (next, [] + seriesopts, _('hg qnext [-s]')), | |
2202 | "qprev": (prev, [] + seriesopts, _('hg qprev [-s]')), |
|
2236 | "qprev": (prev, [] + seriesopts, _('hg qprev [-s]')), | |
@@ -2219,7 +2253,7 b' cmdtable = {' | |||||
2219 | [('e', 'edit', None, _('edit commit message')), |
|
2253 | [('e', 'edit', None, _('edit commit message')), | |
2220 | ('g', 'git', None, _('use git extended diff format')), |
|
2254 | ('g', 'git', None, _('use git extended diff format')), | |
2221 | ('s', 'short', None, _('refresh only files already in the patch')), |
|
2255 | ('s', 'short', None, _('refresh only files already in the patch')), | |
2222 | ] + commands.walkopts + commands.commitopts, |
|
2256 | ] + commands.walkopts + commands.commitopts + headeropts, | |
2223 | _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')), |
|
2257 | _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')), | |
2224 | 'qrename|qmv': |
|
2258 | 'qrename|qmv': | |
2225 | (rename, [], _('hg qrename PATCH1 [PATCH2]')), |
|
2259 | (rename, [], _('hg qrename PATCH1 [PATCH2]')), |
@@ -2029,6 +2029,7 b' def remove(ui, repo, *pats, **opts):' | |||||
2029 | forget.append(abs) |
|
2029 | forget.append(abs) | |
2030 | continue |
|
2030 | continue | |
2031 | reason = _('has been marked for add (use -f to force removal)') |
|
2031 | reason = _('has been marked for add (use -f to force removal)') | |
|
2032 | exact = 1 # force the message | |||
2032 | elif abs not in repo.dirstate: |
|
2033 | elif abs not in repo.dirstate: | |
2033 | reason = _('is not managed') |
|
2034 | reason = _('is not managed') | |
2034 | elif opts['after'] and not exact and abs not in deleted: |
|
2035 | elif opts['after'] and not exact and abs not in deleted: |
@@ -67,7 +67,7 b' class _demandmod(object):' | |||||
67 | return "<proxied module '%s'>" % self._data[0] |
|
67 | return "<proxied module '%s'>" % self._data[0] | |
68 | return "<unloaded module '%s'>" % self._data[0] |
|
68 | return "<unloaded module '%s'>" % self._data[0] | |
69 | def __call__(self, *args, **kwargs): |
|
69 | def __call__(self, *args, **kwargs): | |
70 |
raise TypeError(" |
|
70 | raise TypeError("%s object is not callable" % repr(self)) | |
71 | def __getattribute__(self, attr): |
|
71 | def __getattribute__(self, attr): | |
72 | if attr in ('_data', '_extend', '_load', '_module'): |
|
72 | if attr in ('_data', '_extend', '_load', '_module'): | |
73 | return object.__getattribute__(self, attr) |
|
73 | return object.__getattribute__(self, attr) |
@@ -133,6 +133,8 b' def _runcatch(ui, args):' | |||||
133 |
|
133 | |||
134 | except util.Abort, inst: |
|
134 | except util.Abort, inst: | |
135 | ui.warn(_("abort: %s\n") % inst) |
|
135 | ui.warn(_("abort: %s\n") % inst) | |
|
136 | except MemoryError: | |||
|
137 | ui.warn(_("abort: out of memory\n")) | |||
136 | except SystemExit, inst: |
|
138 | except SystemExit, inst: | |
137 | # Commands shouldn't sys.exit directly, but give a return code. |
|
139 | # Commands shouldn't sys.exit directly, but give a return code. | |
138 | # Just in case catch this and and pass exit code to caller. |
|
140 | # Just in case catch this and and pass exit code to caller. |
@@ -1,35 +1,74 b'' | |||||
1 | import getopt |
|
1 | import getopt | |
2 |
|
2 | |||
3 | def fancyopts(args, options, state): |
|
3 | def fancyopts(args, options, state): | |
4 | long = [] |
|
4 | """ | |
5 | short = '' |
|
5 | read args, parse options, and store options in state | |
6 | map = {} |
|
6 | ||
7 | dt = {} |
|
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: |
|
22 | non-option args are returned | |
10 | pl = l.replace('-', '_') |
|
23 | """ | |
11 | map['-'+s] = map['--'+l] = pl |
|
24 | namelist = [] | |
12 | if isinstance(d, list): |
|
25 | shortlist = '' | |
13 | state[pl] = d[:] |
|
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 | else: |
|
43 | else: | |
15 |
state[ |
|
44 | state[name] = default | |
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) |
|
|||
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: |
|
58 | # transfer result to state | |
27 | if dt[map[opt]] is type(fancyopts): state[map[opt]](state, map[opt], arg) |
|
59 | for opt, val in opts: | |
28 | elif dt[map[opt]] is type(1): state[map[opt]] = int(arg) |
|
60 | name = argmap[opt] | |
29 | elif dt[map[opt]] is type(''): state[map[opt]] = arg |
|
61 | t = type(defmap[name]) | |
30 | elif dt[map[opt]] is type([]): state[map[opt]].append(arg) |
|
62 | if t is type(fancyopts): | |
31 | elif dt[map[opt]] is type(None): state[map[opt]] = True |
|
63 | state[name] = defmap[name](val) | |
32 | elif dt[map[opt]] is type(False): state[map[opt]] = True |
|
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 | return args |
|
74 | return args | |
35 |
|
@@ -280,13 +280,13 b' def update(repo, node):' | |||||
280 | # len(pl)==1, otherwise _merge.update() would have raised util.Abort: |
|
280 | # len(pl)==1, otherwise _merge.update() would have raised util.Abort: | |
281 | repo.ui.status(_(" hg update %s\n hg update %s\n") |
|
281 | repo.ui.status(_(" hg update %s\n hg update %s\n") | |
282 | % (pl[0].rev(), repo.changectx(node).rev())) |
|
282 | % (pl[0].rev(), repo.changectx(node).rev())) | |
283 | return stats[3] |
|
283 | return stats[3] > 0 | |
284 |
|
284 | |||
285 | def clean(repo, node, show_stats=True): |
|
285 | def clean(repo, node, show_stats=True): | |
286 | """forcibly switch the working directory to node, clobbering changes""" |
|
286 | """forcibly switch the working directory to node, clobbering changes""" | |
287 | stats = _merge.update(repo, node, False, True, None) |
|
287 | stats = _merge.update(repo, node, False, True, None) | |
288 | if show_stats: _showstats(repo, stats) |
|
288 | if show_stats: _showstats(repo, stats) | |
289 | return stats[3] |
|
289 | return stats[3] > 0 | |
290 |
|
290 | |||
291 | def merge(repo, node, force=None, remind=True): |
|
291 | def merge(repo, node, force=None, remind=True): | |
292 | """branch merge with node, resolving changes""" |
|
292 | """branch merge with node, resolving changes""" | |
@@ -301,11 +301,11 b' def merge(repo, node, force=None, remind' | |||||
301 | % (pl[0].rev(), pl[1].rev())) |
|
301 | % (pl[0].rev(), pl[1].rev())) | |
302 | elif remind: |
|
302 | elif remind: | |
303 | repo.ui.status(_("(branch merge, don't forget to commit)\n")) |
|
303 | repo.ui.status(_("(branch merge, don't forget to commit)\n")) | |
304 | return stats[3] |
|
304 | return stats[3] > 0 | |
305 |
|
305 | |||
306 | def revert(repo, node, choose): |
|
306 | def revert(repo, node, choose): | |
307 | """revert changes to revision in node without updating dirstate""" |
|
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 | def verify(repo): |
|
310 | def verify(repo): | |
311 | """verify the consistency of a repository""" |
|
311 | """verify the consistency of a repository""" |
@@ -6,18 +6,21 b'' | |||||
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from i18n import _ |
|
8 | from i18n import _ | |
9 | import util |
|
9 | import util, re | |
|
10 | ||||
|
11 | _commentre = None | |||
10 |
|
12 | |||
11 | def _parselines(fp): |
|
13 | def _parselines(fp): | |
12 | for line in fp: |
|
14 | for line in fp: | |
13 |
if n |
|
15 | if "#" in line: | |
14 | line += '\n' |
|
16 | global _commentre | |
15 | escape = False |
|
17 | if not _commentre: | |
16 | for i in xrange(len(line)): |
|
18 | _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*') | |
17 | if escape: escape = False |
|
19 | # remove comments prefixed by an even number of escapes | |
18 | elif line[i] == '\\': escape = True |
|
20 | line = _commentre.sub(r'\1', line) | |
19 | elif line[i] == '#': break |
|
21 | # fixup properly escaped comments that survived the above | |
20 |
line = line |
|
22 | line = line.replace("\\#", "#") | |
|
23 | line = line.rstrip() | |||
21 | if line: |
|
24 | if line: | |
22 | yield line |
|
25 | yield line | |
23 |
|
26 |
@@ -661,6 +661,7 b' class localrepository(repo.repository):' | |||||
661 | match=util.always, force=False, force_editor=False, |
|
661 | match=util.always, force=False, force_editor=False, | |
662 | p1=None, p2=None, extra={}, empty_ok=False): |
|
662 | p1=None, p2=None, extra={}, empty_ok=False): | |
663 | wlock = lock = tr = None |
|
663 | wlock = lock = tr = None | |
|
664 | valid = 0 # don't save the dirstate if this isn't set | |||
664 | try: |
|
665 | try: | |
665 | commit = [] |
|
666 | commit = [] | |
666 | remove = [] |
|
667 | remove = [] | |
@@ -747,6 +748,9 b' class localrepository(repo.repository):' | |||||
747 | if old_exec != new_exec or old_link != new_link: |
|
748 | if old_exec != new_exec or old_link != new_link: | |
748 | changed.append(f) |
|
749 | changed.append(f) | |
749 | m1.set(f, new_exec, new_link) |
|
750 | m1.set(f, new_exec, new_link) | |
|
751 | if use_dirstate: | |||
|
752 | self.dirstate.normal(f) | |||
|
753 | ||||
750 | except (OSError, IOError): |
|
754 | except (OSError, IOError): | |
751 | if use_dirstate: |
|
755 | if use_dirstate: | |
752 | self.ui.warn(_("trouble committing %s!\n") % f) |
|
756 | self.ui.warn(_("trouble committing %s!\n") % f) | |
@@ -817,14 +821,15 b' class localrepository(repo.repository):' | |||||
817 | if use_dirstate or update_dirstate: |
|
821 | if use_dirstate or update_dirstate: | |
818 | self.dirstate.setparents(n) |
|
822 | self.dirstate.setparents(n) | |
819 | if use_dirstate: |
|
823 | if use_dirstate: | |
820 | for f in new: |
|
|||
821 | self.dirstate.normal(f) |
|
|||
822 | for f in removed: |
|
824 | for f in removed: | |
823 | self.dirstate.forget(f) |
|
825 | self.dirstate.forget(f) | |
|
826 | valid = 1 # our dirstate updates are complete | |||
824 |
|
827 | |||
825 | self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) |
|
828 | self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) | |
826 | return n |
|
829 | return n | |
827 | finally: |
|
830 | finally: | |
|
831 | if not valid: # don't save our updated dirstate | |||
|
832 | self.dirstate.invalidate() | |||
828 | del tr, lock, wlock |
|
833 | del tr, lock, wlock | |
829 |
|
834 | |||
830 | def walk(self, node=None, files=[], match=util.always, badmatch=None): |
|
835 | def walk(self, node=None, files=[], match=util.always, badmatch=None): |
@@ -302,24 +302,26 b" unidesc = re.compile('@@ -(\\d+)(,(\\d+))?" | |||||
302 | contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)') |
|
302 | contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)') | |
303 |
|
303 | |||
304 | class patchfile: |
|
304 | class patchfile: | |
305 | def __init__(self, ui, fname): |
|
305 | def __init__(self, ui, fname, missing=False): | |
306 | self.fname = fname |
|
306 | self.fname = fname | |
307 | self.ui = ui |
|
307 | self.ui = ui | |
308 | try: |
|
308 | self.lines = [] | |
309 | fp = file(fname, 'rb') |
|
309 | self.exists = False | |
310 | self.lines = fp.readlines() |
|
310 | self.missing = missing | |
311 | self.exists = True |
|
311 | if not missing: | |
312 | except IOError: |
|
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 | dirname = os.path.dirname(fname) |
|
322 | dirname = os.path.dirname(fname) | |
314 | if dirname and not os.path.isdir(dirname): |
|
323 | if dirname and not os.path.isdir(dirname): | |
315 |
|
|
324 | os.makedirs(dirname) | |
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 |
|
|||
323 |
|
325 | |||
324 | self.hash = {} |
|
326 | self.hash = {} | |
325 | self.dirty = 0 |
|
327 | self.dirty = 0 | |
@@ -427,6 +429,10 b' class patchfile:' | |||||
427 | if reverse: |
|
429 | if reverse: | |
428 | h.reverse() |
|
430 | h.reverse() | |
429 |
|
431 | |||
|
432 | if self.missing: | |||
|
433 | self.rej.append(h) | |||
|
434 | return -1 | |||
|
435 | ||||
430 | if self.exists and h.createfile(): |
|
436 | if self.exists and h.createfile(): | |
431 | self.ui.warn(_("file %s already exists\n") % self.fname) |
|
437 | self.ui.warn(_("file %s already exists\n") % self.fname) | |
432 | self.rej.append(h) |
|
438 | self.rej.append(h) | |
@@ -796,31 +802,32 b' def selectfile(afile_orig, bfile_orig, h' | |||||
796 | nulla = afile_orig == "/dev/null" |
|
802 | nulla = afile_orig == "/dev/null" | |
797 | nullb = bfile_orig == "/dev/null" |
|
803 | nullb = bfile_orig == "/dev/null" | |
798 | afile = pathstrip(afile_orig, strip) |
|
804 | afile = pathstrip(afile_orig, strip) | |
799 |
gooda = os.path.exists(afile) |
|
805 | gooda = not nulla and os.path.exists(afile) | |
800 | bfile = pathstrip(bfile_orig, strip) |
|
806 | bfile = pathstrip(bfile_orig, strip) | |
801 | if afile == bfile: |
|
807 | if afile == bfile: | |
802 | goodb = gooda |
|
808 | goodb = gooda | |
803 | else: |
|
809 | else: | |
804 |
goodb = os.path.exists(bfile) |
|
810 | goodb = not nullb and os.path.exists(bfile) | |
805 | createfunc = hunk.createfile |
|
811 | createfunc = hunk.createfile | |
806 | if reverse: |
|
812 | if reverse: | |
807 | createfunc = hunk.rmfile |
|
813 | createfunc = hunk.rmfile | |
808 |
|
|
814 | missing = not goodb and not gooda and not createfunc() | |
809 | raise PatchError(_("unable to find %s or %s for patching") % |
|
815 | fname = None | |
810 | (afile, bfile)) |
|
816 | if not missing: | |
811 | if gooda and goodb: |
|
817 | if gooda and goodb: | |
812 | fname = bfile |
|
818 | fname = (afile in bfile) and afile or bfile | |
813 | if afile in bfile: |
|
819 | elif gooda: | |
814 | fname = afile |
|
820 | fname = afile | |
815 | elif gooda: |
|
821 | ||
816 | fname = afile |
|
822 | if not fname: | |
817 |
|
|
823 | if not nullb: | |
818 | fname = bfile |
|
824 | fname = (afile in bfile) and afile or bfile | |
819 | if afile in bfile: |
|
825 | elif not nulla: | |
820 | fname = afile |
|
826 | fname = afile | |
821 | elif not nulla: |
|
827 | else: | |
822 | fname = afile |
|
828 | raise PatchError(_("undefined source and destination files")) | |
823 | return fname |
|
829 | ||
|
830 | return fname, missing | |||
824 |
|
831 | |||
825 | class linereader: |
|
832 | class linereader: | |
826 | # simple class to allow pushing lines back into the input stream |
|
833 | # simple class to allow pushing lines back into the input stream | |
@@ -838,14 +845,16 b' class linereader:' | |||||
838 | return l |
|
845 | return l | |
839 | return self.fp.readline() |
|
846 | return self.fp.readline() | |
840 |
|
847 | |||
841 | def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False, |
|
848 | def iterhunks(ui, fp, sourcefile=None): | |
842 | rejmerge=None, updatedir=None): |
|
849 | """Read a patch and yield the following events: | |
843 | """reads a patch from fp and tries to apply it. The dict 'changed' is |
|
850 | - ("file", afile, bfile, firsthunk): select a new target file. | |
844 | filled in with all of the filenames changed by the patch. Returns 0 |
|
851 | - ("hunk", hunk): a new hunk is ready to be applied, follows a | |
845 | for a clean patch, -1 if any rejects were found and 1 if there was |
|
852 | "file" event. | |
846 | any fuzz.""" |
|
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 |
|
857 | def scangitpatch(fp, firstline): | |
849 | '''git patches can modify a file, then copy that file to |
|
858 | '''git patches can modify a file, then copy that file to | |
850 | a new file, but expect the source to be the unmodified form. |
|
859 | a new file, but expect the source to be the unmodified form. | |
851 | So we scan the patch looking for that case so we can do |
|
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 | fp = cStringIO.StringIO(fp.read()) |
|
867 | fp = cStringIO.StringIO(fp.read()) | |
859 |
|
868 | |||
860 | (dopatch, gitpatches) = readgitpatch(fp, firstline) |
|
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 | fp.seek(pos) |
|
870 | fp.seek(pos) | |
866 |
|
871 | |||
867 | return fp, dopatch, gitpatches |
|
872 | return fp, dopatch, gitpatches | |
868 |
|
873 | |||
|
874 | changed = {} | |||
869 | current_hunk = None |
|
875 | current_hunk = None | |
870 | current_file = None |
|
|||
871 | afile = "" |
|
876 | afile = "" | |
872 | bfile = "" |
|
877 | bfile = "" | |
873 | state = None |
|
878 | state = None | |
874 | hunknum = 0 |
|
879 | hunknum = 0 | |
875 | rejects = 0 |
|
880 | emitfile = False | |
876 |
|
881 | |||
877 | git = False |
|
882 | git = False | |
878 | gitre = re.compile('diff --git (a/.*) (b/.*)') |
|
883 | gitre = re.compile('diff --git (a/.*) (b/.*)') | |
879 |
|
884 | |||
880 | # our states |
|
885 | # our states | |
881 | BFILE = 1 |
|
886 | BFILE = 1 | |
882 | err = 0 |
|
|||
883 | context = None |
|
887 | context = None | |
884 | lr = linereader(fp) |
|
888 | lr = linereader(fp) | |
885 | dopatch = True |
|
889 | dopatch = True | |
886 | gitworkdone = False |
|
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 | while True: |
|
892 | while True: | |
902 | newfile = False |
|
893 | newfile = False | |
903 | x = lr.readline() |
|
894 | x = lr.readline() | |
@@ -906,11 +897,7 b' def applydiff(ui, fp, changed, strip=1, ' | |||||
906 | if current_hunk: |
|
897 | if current_hunk: | |
907 | if x.startswith('\ '): |
|
898 | if x.startswith('\ '): | |
908 | current_hunk.fix_newline() |
|
899 | current_hunk.fix_newline() | |
909 | ret = current_file.apply(current_hunk, reverse) |
|
900 | yield 'hunk', current_hunk | |
910 | if ret >= 0: |
|
|||
911 | changed.setdefault(current_file.fname, (None, None)) |
|
|||
912 | if ret > 0: |
|
|||
913 | err = 1 |
|
|||
914 | current_hunk = None |
|
901 | current_hunk = None | |
915 | gitworkdone = False |
|
902 | gitworkdone = False | |
916 | if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or |
|
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 | current_hunk = None |
|
911 | current_hunk = None | |
925 | continue |
|
912 | continue | |
926 | hunknum += 1 |
|
913 | hunknum += 1 | |
927 |
if |
|
914 | if emitfile: | |
928 | current_file = getpatchfile(afile, bfile, current_hunk) |
|
915 | emitfile = False | |
929 | if not current_file: |
|
916 | yield 'file', (afile, bfile, current_hunk) | |
930 | current_file, current_hunk = None, None |
|
|||
931 | rejects += 1 |
|
|||
932 | continue |
|
|||
933 | elif state == BFILE and x.startswith('GIT binary patch'): |
|
917 | elif state == BFILE and x.startswith('GIT binary patch'): | |
934 | current_hunk = binhunk(changed[bfile[2:]][1]) |
|
918 | current_hunk = binhunk(changed[bfile[2:]][1]) | |
935 | hunknum += 1 |
|
919 | hunknum += 1 | |
936 |
if |
|
920 | if emitfile: | |
937 | current_file = getpatchfile(afile, bfile, current_hunk) |
|
921 | emitfile = False | |
938 | if not current_file: |
|
922 | yield 'file', (afile, bfile, current_hunk) | |
939 | current_file, current_hunk = None, None |
|
|||
940 | rejects += 1 |
|
|||
941 | continue |
|
|||
942 | current_hunk.extract(fp) |
|
923 | current_hunk.extract(fp) | |
943 | elif x.startswith('diff --git'): |
|
924 | elif x.startswith('diff --git'): | |
944 | # check for git diff, scanning the whole patch file if needed |
|
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 | if not git: |
|
929 | if not git: | |
949 | git = True |
|
930 | git = True | |
950 | fp, dopatch, gitpatches = scangitpatch(fp, x) |
|
931 | fp, dopatch, gitpatches = scangitpatch(fp, x) | |
|
932 | yield 'git', gitpatches | |||
951 | for gp in gitpatches: |
|
933 | for gp in gitpatches: | |
952 | changed[gp.path] = (gp.op, gp) |
|
934 | changed[gp.path] = (gp.op, gp) | |
953 | # else error? |
|
935 | # else error? | |
@@ -984,36 +966,79 b' def applydiff(ui, fp, changed, strip=1, ' | |||||
984 | bfile = parsefilename(l2) |
|
966 | bfile = parsefilename(l2) | |
985 |
|
967 | |||
986 | if newfile: |
|
968 | if newfile: | |
987 |
if |
|
969 | emitfile = True | |
988 | current_file.close() |
|
|||
989 | if rejmerge: |
|
|||
990 | rejmerge(current_file) |
|
|||
991 | rejects += len(current_file.rej) |
|
|||
992 | state = BFILE |
|
970 | state = BFILE | |
993 | current_file = None |
|
|||
994 | hunknum = 0 |
|
971 | hunknum = 0 | |
995 | if current_hunk: |
|
972 | if current_hunk: | |
996 | if current_hunk.complete(): |
|
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 | ret = current_file.apply(current_hunk, reverse) |
|
1007 | ret = current_file.apply(current_hunk, reverse) | |
998 | if ret >= 0: |
|
1008 | if ret >= 0: | |
999 | changed.setdefault(current_file.fname, (None, None)) |
|
1009 | changed.setdefault(current_file.fname, (None, None)) | |
1000 | if ret > 0: |
|
1010 | if ret > 0: | |
1001 | err = 1 |
|
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 | else: |
|
1033 | else: | |
1003 | fname = current_file and current_file.fname or None |
|
1034 | raise util.Abort(_('unsupported parser state: %s') % state) | |
1004 | raise PatchError(_("malformed patch %s %s") % (fname, |
|
1035 | ||
1005 | current_hunk.desc)) |
|
1036 | rejects += closefile() | |
1006 | if current_file: |
|
1037 | ||
1007 | current_file.close() |
|
1038 | if updatedir and gitpatches: | |
1008 | if rejmerge: |
|
|||
1009 | rejmerge(current_file) |
|
|||
1010 | rejects += len(current_file.rej) |
|
|||
1011 | if updatedir and git: |
|
|||
1012 | updatedir(gitpatches) |
|
1039 | updatedir(gitpatches) | |
1013 | if rejects: |
|
1040 | if rejects: | |
1014 | return -1 |
|
1041 | return -1 | |
1015 | if hunknum == 0 and dopatch and not gitworkdone: |
|
|||
1016 | raise NoHunks |
|
|||
1017 | return err |
|
1042 | return err | |
1018 |
|
1043 | |||
1019 | def diffopts(ui, opts={}, untrusted=False): |
|
1044 | def diffopts(ui, opts={}, untrusted=False): |
@@ -919,7 +919,15 b" if os.name == 'nt':" | |||||
919 |
|
919 | |||
920 | def write(self, s): |
|
920 | def write(self, s): | |
921 | try: |
|
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 | except IOError, inst: |
|
931 | except IOError, inst: | |
924 | if inst.errno != 0: raise |
|
932 | if inst.errno != 0: raise | |
925 | self.close() |
|
933 | self.close() |
@@ -41,6 +41,8 b' hg qpush' | |||||
41 | echo % display added files |
|
41 | echo % display added files | |
42 | cat a |
|
42 | cat a | |
43 | cat c |
|
43 | cat c | |
|
44 | echo % display rejections | |||
|
45 | cat b.rej | |||
44 | cd .. |
|
46 | cd .. | |
45 |
|
47 | |||
46 |
|
48 | |||
@@ -65,5 +67,7 b' hg st' | |||||
65 | echo % display added files |
|
67 | echo % display added files | |
66 | cat a |
|
68 | cat a | |
67 | cat c |
|
69 | cat c | |
|
70 | echo % display rejections | |||
|
71 | cat b.rej | |||
68 | cd .. |
|
72 | cd .. | |
69 |
|
73 |
@@ -2,24 +2,48 b' adding b' | |||||
2 | Patch queue now empty |
|
2 | Patch queue now empty | |
3 | % push patch with missing target |
|
3 | % push patch with missing target | |
4 | applying changeb |
|
4 | applying changeb | |
5 |
unable to find |
|
5 | unable to find 'b' for patching | |
6 | unable to find b or b for patching |
|
6 | 2 out of 2 hunks FAILED -- saving rejects to file b.rej | |
7 | patch failed, unable to continue (try -v) |
|
7 | patch failed, unable to continue (try -v) | |
8 | patch failed, rejects left in working dir |
|
8 | patch failed, rejects left in working dir | |
9 | Errors during apply, please fix and refresh changeb |
|
9 | Errors during apply, please fix and refresh changeb | |
10 | % display added files |
|
10 | % display added files | |
11 | a |
|
11 | a | |
12 | c |
|
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 | adding b |
|
28 | adding b | |
14 | Patch queue now empty |
|
29 | Patch queue now empty | |
15 | % push git patch with missing target |
|
30 | % push git patch with missing target | |
16 | applying changeb |
|
31 | applying changeb | |
17 |
unable to find |
|
32 | unable to find 'b' for patching | |
|
33 | 1 out of 1 hunk FAILED -- saving rejects to file b.rej | |||
18 | patch failed, unable to continue (try -v) |
|
34 | patch failed, unable to continue (try -v) | |
19 | b: No such file or directory |
|
35 | b: No such file or directory | |
20 | b not tracked! |
|
36 | b not tracked! | |
21 | patch failed, rejects left in working dir |
|
37 | patch failed, rejects left in working dir | |
22 | Errors during apply, please fix and refresh changeb |
|
38 | Errors during apply, please fix and refresh changeb | |
|
39 | ? b.rej | |||
23 | % display added files |
|
40 | % display added files | |
24 | a |
|
41 | a | |
25 | c |
|
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