Show More
@@ -2357,11 +2357,28 b' def save(ui, repo, **opts):' | |||||
2357 | return 0 |
|
2357 | return 0 | |
2358 |
|
2358 | |||
2359 | def strip(ui, repo, rev, **opts): |
|
2359 | def strip(ui, repo, rev, **opts): | |
2360 |
"""strip a |
|
2360 | """strip a changeset and all its descendants from the repository | |
|
2361 | ||||
|
2362 | The strip command removes all changesets whose local revision | |||
|
2363 | number is greater than or equal to REV, and then restores any | |||
|
2364 | changesets that are not descendants of REV. If the working | |||
|
2365 | directory has uncommitted changes, the operation is aborted unless | |||
|
2366 | the --force flag is supplied. | |||
2361 |
|
2367 | |||
2362 |
If |
|
2368 | If a parent of the working directory is stripped, then the working | |
2363 |
|
|
2369 | directory will automatically be updated to the most recent | |
2364 | revision. |
|
2370 | available ancestor of the stripped parent after the operation | |
|
2371 | completes. | |||
|
2372 | ||||
|
2373 | Any stripped changesets are stored in ``.hg/strip-backup`` as a | |||
|
2374 | bundle (see ``hg help bundle`` and ``hg help unbundle``). They can | |||
|
2375 | be restored by running ``hg unbundle .hg/strip-backup/BUNDLE``, | |||
|
2376 | where BUNDLE is the bundle file created by the strip. Note that | |||
|
2377 | the local revision numbers will in general be different after the | |||
|
2378 | restore. | |||
|
2379 | ||||
|
2380 | Use the --nobackup option to discard the backup bundle once the | |||
|
2381 | operation completes. | |||
2365 | """ |
|
2382 | """ | |
2366 | backup = 'all' |
|
2383 | backup = 'all' | |
2367 | if opts['backup']: |
|
2384 | if opts['backup']: | |
@@ -2788,14 +2805,17 b' cmdtable = {' | |||||
2788 | (series, |
|
2805 | (series, | |
2789 | [('m', 'missing', None, _('print patches not in series')), |
|
2806 | [('m', 'missing', None, _('print patches not in series')), | |
2790 | ] + seriesopts, |
|
2807 | ] + seriesopts, | |
2791 | _('hg qseries [-ms]')), |
|
2808 | _('hg qseries [-ms]')), | |
2792 | "strip": |
|
2809 | "strip": | |
2793 | (strip, |
|
2810 | (strip, | |
2794 |
[('f', 'force', None, _('force removal |
|
2811 | [('f', 'force', None, _('force removal of changesets even if the ' | |
2795 | ('b', 'backup', None, _('bundle unrelated changesets')), |
|
2812 | 'working directory has uncommitted changes')), | |
2796 |
(' |
|
2813 | ('b', 'backup', None, _('bundle only changesets with local revision' | |
2797 | _('hg strip [-f] [-b] [-n] REV')), |
|
2814 | ' number greater than REV which are not' | |
2798 | "qtop": (top, [] + seriesopts, _('hg qtop [-s]')), |
|
2815 | ' descendants of REV (DEPRECATED)')), | |
|
2816 | ('n', 'nobackup', None, _('no backups'))], | |||
|
2817 | _('hg strip [-f] [-b] [-n] REV')), | |||
|
2818 | "qtop": (top, [] + seriesopts, _('hg qtop [-s]')), | |||
2799 | "qunapplied": |
|
2819 | "qunapplied": | |
2800 | (unapplied, |
|
2820 | (unapplied, | |
2801 | [('1', 'first', None, _('show only the first patch'))] + seriesopts, |
|
2821 | [('1', 'first', None, _('show only the first patch'))] + seriesopts, |
@@ -2474,7 +2474,8 b' def push(ui, repo, dest=None, **opts):' | |||||
2474 | c = repo[''] |
|
2474 | c = repo[''] | |
2475 | subs = c.substate # only repos that are committed |
|
2475 | subs = c.substate # only repos that are committed | |
2476 | for s in sorted(subs): |
|
2476 | for s in sorted(subs): | |
2477 | c.sub(s).push(opts.get('force')) |
|
2477 | if not c.sub(s).push(opts.get('force')): | |
|
2478 | return False | |||
2478 |
|
2479 | |||
2479 | r = repo.push(other, opts.get('force'), revs=revs) |
|
2480 | r = repo.push(other, opts.get('force'), revs=revs) | |
2480 | return r == 0 |
|
2481 | return r == 0 |
@@ -18,6 +18,7 b' class httprangereader(object):' | |||||
18 | self.url = url |
|
18 | self.url = url | |
19 | self.pos = 0 |
|
19 | self.pos = 0 | |
20 | self.opener = opener |
|
20 | self.opener = opener | |
|
21 | self.name = url | |||
21 | def seek(self, pos): |
|
22 | def seek(self, pos): | |
22 | self.pos = pos |
|
23 | self.pos = pos | |
23 | def read(self, bytes=None): |
|
24 | def read(self, bytes=None): | |
@@ -56,6 +57,10 b' class httprangereader(object):' | |||||
56 | data = data[:bytes] |
|
57 | data = data[:bytes] | |
57 | self.pos += len(data) |
|
58 | self.pos += len(data) | |
58 | return data |
|
59 | return data | |
|
60 | def __iter__(self): | |||
|
61 | return iter(self.read().splitlines(1)) | |||
|
62 | def close(self): | |||
|
63 | pass | |||
59 |
|
64 | |||
60 | def build_opener(ui, authinfo): |
|
65 | def build_opener(ui, authinfo): | |
61 | # urllib cannot handle URLs with embedded user or passwd |
|
66 | # urllib cannot handle URLs with embedded user or passwd | |
@@ -65,7 +70,9 b' def build_opener(ui, authinfo):' | |||||
65 | def opener(base): |
|
70 | def opener(base): | |
66 | """return a function that opens files over http""" |
|
71 | """return a function that opens files over http""" | |
67 | p = base |
|
72 | p = base | |
68 | def o(path, mode="r"): |
|
73 | def o(path, mode="r", atomictemp=None): | |
|
74 | if 'a' in mode or 'w' in mode: | |||
|
75 | raise IOError('Permission denied') | |||
69 | f = "/".join((p, urllib.quote(path))) |
|
76 | f = "/".join((p, urllib.quote(path))) | |
70 | return httprangereader(f, urlopener) |
|
77 | return httprangereader(f, urlopener) | |
71 | return o |
|
78 | return o | |
@@ -77,6 +84,7 b' class statichttprepository(localrepo.loc' | |||||
77 | self._url = path |
|
84 | self._url = path | |
78 | self.ui = ui |
|
85 | self.ui = ui | |
79 |
|
86 | |||
|
87 | self.root = path | |||
80 | self.path, authinfo = url.getauthinfo(path.rstrip('/') + "/.hg") |
|
88 | self.path, authinfo = url.getauthinfo(path.rstrip('/') + "/.hg") | |
81 |
|
89 | |||
82 | opener = build_opener(ui, authinfo) |
|
90 | opener = build_opener(ui, authinfo) | |
@@ -116,6 +124,8 b' class statichttprepository(localrepo.loc' | |||||
116 | self.changelog = changelog.changelog(self.sopener) |
|
124 | self.changelog = changelog.changelog(self.sopener) | |
117 | self._tags = None |
|
125 | self._tags = None | |
118 | self.nodetagscache = None |
|
126 | self.nodetagscache = None | |
|
127 | self._branchcache = None | |||
|
128 | self._branchcachetip = None | |||
119 | self.encodepats = None |
|
129 | self.encodepats = None | |
120 | self.decodepats = None |
|
130 | self.decodepats = None | |
121 |
|
131 |
@@ -259,12 +259,13 b' class hgsubrepo(object):' | |||||
259 | c = self._repo[''] |
|
259 | c = self._repo[''] | |
260 | subs = c.substate # only repos that are committed |
|
260 | subs = c.substate # only repos that are committed | |
261 | for s in sorted(subs): |
|
261 | for s in sorted(subs): | |
262 | c.sub(s).push(force) |
|
262 | if not c.sub(s).push(force): | |
|
263 | return False | |||
263 |
|
264 | |||
264 | self._repo.ui.status(_('pushing subrepo %s\n') % self._path) |
|
265 | self._repo.ui.status(_('pushing subrepo %s\n') % self._path) | |
265 | dsturl = _abssource(self._repo, True) |
|
266 | dsturl = _abssource(self._repo, True) | |
266 | other = hg.repository(self._repo.ui, dsturl) |
|
267 | other = hg.repository(self._repo.ui, dsturl) | |
267 | self._repo.push(other, force) |
|
268 | return self._repo.push(other, force) | |
268 |
|
269 | |||
269 | class svnsubrepo(object): |
|
270 | class svnsubrepo(object): | |
270 | def __init__(self, ctx, path, state): |
|
271 | def __init__(self, ctx, path, state): |
@@ -197,6 +197,8 b' def _readtagcache(ui, repo):' | |||||
197 |
|
197 | |||
198 | try: |
|
198 | try: | |
199 | cachefile = repo.opener('tags.cache', 'r') |
|
199 | cachefile = repo.opener('tags.cache', 'r') | |
|
200 | # force reading the file for static-http | |||
|
201 | cachelines = iter(cachefile) | |||
200 | _debug(ui, 'reading tag cache from %s\n' % cachefile.name) |
|
202 | _debug(ui, 'reading tag cache from %s\n' % cachefile.name) | |
201 | except IOError: |
|
203 | except IOError: | |
202 | cachefile = None |
|
204 | cachefile = None | |
@@ -217,7 +219,7 b' def _readtagcache(ui, repo):' | |||||
217 | cacheheads = [] # list of headnode |
|
219 | cacheheads = [] # list of headnode | |
218 | cachefnode = {} # map headnode to filenode |
|
220 | cachefnode = {} # map headnode to filenode | |
219 | if cachefile: |
|
221 | if cachefile: | |
220 |
for line in cache |
|
222 | for line in cachelines: | |
221 | if line == "\n": |
|
223 | if line == "\n": | |
222 | break |
|
224 | break | |
223 | line = line.rstrip().split() |
|
225 | line = line.rstrip().split() | |
@@ -237,7 +239,7 b' def _readtagcache(ui, repo):' | |||||
237 | # have been destroyed by strip or rollback.) |
|
239 | # have been destroyed by strip or rollback.) | |
238 | if cacheheads and cacheheads[0] == tipnode and cacherevs[0] == tiprev: |
|
240 | if cacheheads and cacheheads[0] == tipnode and cacherevs[0] == tiprev: | |
239 | _debug(ui, "tag cache: tip unchanged\n") |
|
241 | _debug(ui, "tag cache: tip unchanged\n") | |
240 |
tags = _readtags(ui, repo, cache |
|
242 | tags = _readtags(ui, repo, cachelines, cachefile.name) | |
241 | cachefile.close() |
|
243 | cachefile.close() | |
242 | return (None, None, tags, False) |
|
244 | return (None, None, tags, False) | |
243 | if cachefile: |
|
245 | if cachefile: |
@@ -156,6 +156,7 b' hg debugextensions' | |||||
156 |
|
156 | |||
157 | echo '% disabled extension commands' |
|
157 | echo '% disabled extension commands' | |
158 | HGRCPATH= |
|
158 | HGRCPATH= | |
|
159 | export HGRCPATH | |||
159 | hg help email |
|
160 | hg help email | |
160 | hg qdel |
|
161 | hg qdel | |
161 | hg churn |
|
162 | hg churn |
@@ -28,7 +28,7 b' EOF' | |||||
28 |
|
28 | |||
29 | cat >> $HGRCPATH <<EOF |
|
29 | cat >> $HGRCPATH <<EOF | |
30 | [extensions] |
|
30 | [extensions] | |
31 |
commitwrapper = |
|
31 | commitwrapper = `pwd`/commitwrapper.py | |
32 | EOF |
|
32 | EOF | |
33 |
|
33 | |||
34 | hg init repo1 |
|
34 | hg init repo1 |
@@ -28,7 +28,7 b' hg rm a' | |||||
28 | hg qrefresh -m "rm a" |
|
28 | hg qrefresh -m "rm a" | |
29 |
|
29 | |||
30 | # Save the patch queue so we can merge it later |
|
30 | # Save the patch queue so we can merge it later | |
31 | hg qsave -c -e 2>&1 | grep -v ^copy |
|
31 | hg qsave -c -e 2>&1 | grep -v '^copy' | |
32 | checkundo qsave |
|
32 | checkundo qsave | |
33 |
|
33 | |||
34 | # Update b and commit in an "update" changeset |
|
34 | # Update b and commit in an "update" changeset | |
@@ -40,7 +40,7 b' hg ci -m update' | |||||
40 | # Here, qpush used to abort with : |
|
40 | # Here, qpush used to abort with : | |
41 | # The system cannot find the file specified => a |
|
41 | # The system cannot find the file specified => a | |
42 | hg manifest |
|
42 | hg manifest | |
43 | hg qpush -a -m 2>&1 | grep -v ^merging |
|
43 | hg qpush -a -m 2>&1 | grep -v '^merging' | |
44 | checkundo 'qpush -m' |
|
44 | checkundo 'qpush -m' | |
45 | hg manifest |
|
45 | hg manifest | |
46 |
|
46 |
@@ -55,7 +55,7 b' list of commands:' | |||||
55 | qseries print the entire series file |
|
55 | qseries print the entire series file | |
56 | qtop print the name of the current patch |
|
56 | qtop print the name of the current patch | |
57 | qunapplied print the patches not yet applied |
|
57 | qunapplied print the patches not yet applied | |
58 |
strip strip a |
|
58 | strip strip a changeset and all its descendants from the repository | |
59 |
|
59 | |||
60 | use "hg -v help mq" to show aliases and global options |
|
60 | use "hg -v help mq" to show aliases and global options | |
61 | adding a |
|
61 | adding a |
@@ -43,6 +43,8 b' cat bar' | |||||
43 | cd ../remote |
|
43 | cd ../remote | |
44 | echo baz > quux |
|
44 | echo baz > quux | |
45 | hg commit -A -mtest2 -d '100000000 0' |
|
45 | hg commit -A -mtest2 -d '100000000 0' | |
|
46 | # check for HTTP opener failures when cachefile does not exist | |||
|
47 | rm .hg/*.cache | |||
46 |
|
48 | |||
47 | cd ../local |
|
49 | cd ../local | |
48 | echo '[hooks]' >> .hg/hgrc |
|
50 | echo '[hooks]' >> .hg/hgrc | |
@@ -55,8 +57,12 b' echo more foo >> bar' | |||||
55 | hg commit -m"test" -d "100000000 0" |
|
57 | hg commit -m"test" -d "100000000 0" | |
56 | hg push | sed -e "s,:$HGPORT/,:\$HGPORT/," |
|
58 | hg push | sed -e "s,:$HGPORT/,:\$HGPORT/," | |
57 |
|
59 | |||
|
60 | echo '% trying clone -r' | |||
|
61 | cd .. | |||
|
62 | hg clone -r donotexist static-http://localhost:$HGPORT/remote local0 | sed -e "s,:$HGPORT/,:\$HGPORT/," | |||
|
63 | hg clone -r 0 static-http://localhost:$HGPORT/remote local0 | sed -e "s,:$HGPORT/,:\$HGPORT/," | |||
|
64 | ||||
58 | echo '% test with "/" URI (issue 747)' |
|
65 | echo '% test with "/" URI (issue 747)' | |
59 | cd .. |
|
|||
60 | hg init |
|
66 | hg init | |
61 | echo a > a |
|
67 | echo a > a | |
62 | hg add a |
|
68 | hg add a |
@@ -33,6 +33,15 b' added 1 changesets with 1 changes to 1 f' | |||||
33 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
33 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
34 | abort: cannot lock static-http repository |
|
34 | abort: cannot lock static-http repository | |
35 | pushing to static-http://localhost:$HGPORT/remote |
|
35 | pushing to static-http://localhost:$HGPORT/remote | |
|
36 | % trying clone -r | |||
|
37 | abort: unknown revision 'donotexist'! | |||
|
38 | requesting all changes | |||
|
39 | adding changesets | |||
|
40 | adding manifests | |||
|
41 | adding file changes | |||
|
42 | added 1 changesets with 1 changes to 1 files | |||
|
43 | updating to branch default | |||
|
44 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
36 | % test with "/" URI (issue 747) |
|
45 | % test with "/" URI (issue 747) | |
37 | requesting all changes |
|
46 | requesting all changes | |
38 | adding changesets |
|
47 | adding changesets |
@@ -208,4 +208,24 b' cat mercurial2/main/nested_absolute/.hg/' | |||||
208 | | "$TESTDIR/filtertmp.py" |
|
208 | | "$TESTDIR/filtertmp.py" | |
209 | rm -rf mercurial mercurial2 |
|
209 | rm -rf mercurial mercurial2 | |
210 |
|
210 | |||
|
211 | echo % issue 1977 | |||
|
212 | hg init repo | |||
|
213 | hg init repo/s | |||
|
214 | echo a > repo/s/a | |||
|
215 | hg -R repo/s ci -Am0 | |||
|
216 | echo s = s > repo/.hgsub | |||
|
217 | hg -R repo ci -Am1 | |||
|
218 | hg clone repo repo2 | |||
|
219 | hg -q -R repo2 pull -u | |||
|
220 | echo 1 > repo2/s/a | |||
|
221 | hg -R repo2/s ci -m2 | |||
|
222 | hg -q -R repo2/s push | |||
|
223 | hg -R repo2/s up -C 0 | |||
|
224 | echo 2 > repo2/s/a | |||
|
225 | hg -R repo2/s ci -m3 | |||
|
226 | hg -R repo2 ci -m3 | |||
|
227 | hg -q -R repo2 push | |||
|
228 | hg -R repo update | |||
|
229 | rm -rf repo2 repo | |||
|
230 | ||||
211 | exit 0 |
|
231 | exit 0 |
@@ -163,14 +163,6 b' no changes found' | |||||
163 | pushing ...subrepo s |
|
163 | pushing ...subrepo s | |
164 | searching for changes |
|
164 | searching for changes | |
165 | (did you forget to merge? use push -f to force) |
|
165 | (did you forget to merge? use push -f to force) | |
166 | pushing ...subrepo t |
|
|||
167 | searching for changes |
|
|||
168 | no changes found |
|
|||
169 | searching for changes |
|
|||
170 | adding changesets |
|
|||
171 | adding manifests |
|
|||
172 | adding file changes |
|
|||
173 | added 1 changesets with 1 changes to 1 files |
|
|||
174 | pushing ...sub/t |
|
166 | pushing ...sub/t | |
175 | pushing ...subrepo ss |
|
167 | pushing ...subrepo ss | |
176 | searching for changes |
|
168 | searching for changes | |
@@ -185,7 +177,10 b' pushing ...subrepo t' | |||||
185 | searching for changes |
|
177 | searching for changes | |
186 | no changes found |
|
178 | no changes found | |
187 | searching for changes |
|
179 | searching for changes | |
188 | no changes found |
|
180 | adding changesets | |
|
181 | adding manifests | |||
|
182 | adding file changes | |||
|
183 | added 1 changesets with 1 changes to 1 files | |||
189 | % update |
|
184 | % update | |
190 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
185 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
191 | committing subrepository t |
|
186 | committing subrepository t | |
@@ -266,3 +261,20 b' 2 files updated, 0 files merged, 0 files' | |||||
266 | default = $HGTMP/test-subrepo/sub/mercurial/nested_absolute |
|
261 | default = $HGTMP/test-subrepo/sub/mercurial/nested_absolute | |
267 | [paths] |
|
262 | [paths] | |
268 | default = $HGTMP/test-subrepo/sub/mercurial/main/../nested_relative |
|
263 | default = $HGTMP/test-subrepo/sub/mercurial/main/../nested_relative | |
|
264 | % issue 1977 | |||
|
265 | adding a | |||
|
266 | adding .hgsub | |||
|
267 | committing subrepository s | |||
|
268 | updating to branch default | |||
|
269 | pulling subrepo s | |||
|
270 | requesting all changes | |||
|
271 | adding changesets | |||
|
272 | adding manifests | |||
|
273 | adding file changes | |||
|
274 | added 1 changesets with 1 changes to 1 files | |||
|
275 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
276 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
277 | created new head | |||
|
278 | committing subrepository s | |||
|
279 | abort: push creates new remote heads on branch 'default'! | |||
|
280 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
General Comments 0
You need to be logged in to leave comments.
Login now