18 registrar, |
18 registrar, |
19 repair, |
19 repair, |
20 scmutil, |
20 scmutil, |
21 util, |
21 util, |
22 ) |
22 ) |
|
23 |
23 nullid = nodemod.nullid |
24 nullid = nodemod.nullid |
24 release = lockmod.release |
25 release = lockmod.release |
25 |
26 |
26 cmdtable = {} |
27 cmdtable = {} |
27 command = registrar.command(cmdtable) |
28 command = registrar.command(cmdtable) |
28 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for |
29 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for |
29 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should |
30 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should |
30 # be specifying the version(s) of Mercurial they are tested with, or |
31 # be specifying the version(s) of Mercurial they are tested with, or |
31 # leave the attribute unspecified. |
32 # leave the attribute unspecified. |
32 testedwith = 'ships-with-hg-core' |
33 testedwith = 'ships-with-hg-core' |
|
34 |
33 |
35 |
34 def checklocalchanges(repo, force=False): |
36 def checklocalchanges(repo, force=False): |
35 s = repo.status() |
37 s = repo.status() |
36 if not force: |
38 if not force: |
37 cmdutil.checkunfinished(repo) |
39 cmdutil.checkunfinished(repo) |
38 cmdutil.bailifchanged(repo) |
40 cmdutil.bailifchanged(repo) |
39 else: |
41 else: |
40 cmdutil.checkunfinished(repo, skipmerge=True) |
42 cmdutil.checkunfinished(repo, skipmerge=True) |
41 return s |
43 return s |
42 |
44 |
|
45 |
43 def _findupdatetarget(repo, nodes): |
46 def _findupdatetarget(repo, nodes): |
44 unode, p2 = repo.changelog.parents(nodes[0]) |
47 unode, p2 = repo.changelog.parents(nodes[0]) |
45 currentbranch = repo[None].branch() |
48 currentbranch = repo[None].branch() |
46 |
49 |
47 if (util.safehasattr(repo, 'mq') and p2 != nullid |
50 if ( |
48 and p2 in [x.node for x in repo.mq.applied]): |
51 util.safehasattr(repo, 'mq') |
|
52 and p2 != nullid |
|
53 and p2 in [x.node for x in repo.mq.applied] |
|
54 ): |
49 unode = p2 |
55 unode = p2 |
50 elif currentbranch != repo[unode].branch(): |
56 elif currentbranch != repo[unode].branch(): |
51 pwdir = 'parents(wdir())' |
57 pwdir = 'parents(wdir())' |
52 revset = 'max(((parents(%ln::%r) + %r) - %ln::%r) and branch(%s))' |
58 revset = 'max(((parents(%ln::%r) + %r) - %ln::%r) and branch(%s))' |
53 branchtarget = repo.revs(revset, nodes, pwdir, pwdir, nodes, pwdir, |
59 branchtarget = repo.revs( |
54 currentbranch) |
60 revset, nodes, pwdir, pwdir, nodes, pwdir, currentbranch |
|
61 ) |
55 if branchtarget: |
62 if branchtarget: |
56 cl = repo.changelog |
63 cl = repo.changelog |
57 unode = cl.node(branchtarget.first()) |
64 unode = cl.node(branchtarget.first()) |
58 |
65 |
59 return unode |
66 return unode |
60 |
67 |
61 def strip(ui, repo, revs, update=True, backup=True, force=None, bookmarks=None, |
68 |
62 soft=False): |
69 def strip( |
|
70 ui, |
|
71 repo, |
|
72 revs, |
|
73 update=True, |
|
74 backup=True, |
|
75 force=None, |
|
76 bookmarks=None, |
|
77 soft=False, |
|
78 ): |
63 with repo.wlock(), repo.lock(): |
79 with repo.wlock(), repo.lock(): |
64 |
80 |
65 if update: |
81 if update: |
66 checklocalchanges(repo, force=force) |
82 checklocalchanges(repo, force=force) |
67 urev = _findupdatetarget(repo, revs) |
83 urev = _findupdatetarget(repo, revs) |
80 bookmarksmod.deactivate(repo) |
96 bookmarksmod.deactivate(repo) |
81 repomarks.applychanges(repo, tr, [(b, None) for b in bookmarks]) |
97 repomarks.applychanges(repo, tr, [(b, None) for b in bookmarks]) |
82 for bookmark in sorted(bookmarks): |
98 for bookmark in sorted(bookmarks): |
83 ui.write(_("bookmark '%s' deleted\n") % bookmark) |
99 ui.write(_("bookmark '%s' deleted\n") % bookmark) |
84 |
100 |
85 @command("strip", |
101 |
86 [ |
102 @command( |
87 ('r', 'rev', [], _('strip specified revision (optional, ' |
103 "strip", |
88 'can specify revisions without this ' |
104 [ |
89 'option)'), _('REV')), |
105 ( |
90 ('f', 'force', None, _('force removal of changesets, discard ' |
106 'r', |
91 'uncommitted changes (no backup)')), |
107 'rev', |
92 ('', 'no-backup', None, _('do not save backup bundle')), |
108 [], |
93 ('', 'nobackup', None, _('do not save backup bundle ' |
109 _( |
94 '(DEPRECATED)')), |
110 'strip specified revision (optional, ' |
95 ('n', '', None, _('ignored (DEPRECATED)')), |
111 'can specify revisions without this ' |
96 ('k', 'keep', None, _("do not modify working directory during " |
112 'option)' |
97 "strip")), |
113 ), |
98 ('B', 'bookmark', [], _("remove revs only reachable from given" |
114 _('REV'), |
99 " bookmark"), _('BOOKMARK')), |
115 ), |
100 ('', 'soft', None, |
116 ( |
101 _("simply drop changesets from visible history (EXPERIMENTAL)")), |
117 'f', |
102 ], |
118 'force', |
103 _('hg strip [-k] [-f] [-B bookmark] [-r] REV...'), |
119 None, |
104 helpcategory=command.CATEGORY_MAINTENANCE) |
120 _( |
|
121 'force removal of changesets, discard ' |
|
122 'uncommitted changes (no backup)' |
|
123 ), |
|
124 ), |
|
125 ('', 'no-backup', None, _('do not save backup bundle')), |
|
126 ('', 'nobackup', None, _('do not save backup bundle ' '(DEPRECATED)')), |
|
127 ('n', '', None, _('ignored (DEPRECATED)')), |
|
128 ( |
|
129 'k', |
|
130 'keep', |
|
131 None, |
|
132 _("do not modify working directory during " "strip"), |
|
133 ), |
|
134 ( |
|
135 'B', |
|
136 'bookmark', |
|
137 [], |
|
138 _("remove revs only reachable from given" " bookmark"), |
|
139 _('BOOKMARK'), |
|
140 ), |
|
141 ( |
|
142 '', |
|
143 'soft', |
|
144 None, |
|
145 _("simply drop changesets from visible history (EXPERIMENTAL)"), |
|
146 ), |
|
147 ], |
|
148 _('hg strip [-k] [-f] [-B bookmark] [-r] REV...'), |
|
149 helpcategory=command.CATEGORY_MAINTENANCE, |
|
150 ) |
105 def stripcmd(ui, repo, *revs, **opts): |
151 def stripcmd(ui, repo, *revs, **opts): |
106 """strip changesets and all their descendants from the repository |
152 """strip changesets and all their descendants from the repository |
107 |
153 |
108 The strip command removes the specified changesets and all their |
154 The strip command removes the specified changesets and all their |
109 descendants. If the working directory has uncommitted changes, the |
155 descendants. If the working directory has uncommitted changes, the |
143 with repo.wlock(): |
189 with repo.wlock(): |
144 bookmarks = set(opts.get('bookmark')) |
190 bookmarks = set(opts.get('bookmark')) |
145 if bookmarks: |
191 if bookmarks: |
146 repomarks = repo._bookmarks |
192 repomarks = repo._bookmarks |
147 if not bookmarks.issubset(repomarks): |
193 if not bookmarks.issubset(repomarks): |
148 raise error.Abort(_("bookmark '%s' not found") % |
194 raise error.Abort( |
149 ','.join(sorted(bookmarks - set(repomarks.keys())))) |
195 _("bookmark '%s' not found") |
|
196 % ','.join(sorted(bookmarks - set(repomarks.keys()))) |
|
197 ) |
150 |
198 |
151 # If the requested bookmark is not the only one pointing to a |
199 # If the requested bookmark is not the only one pointing to a |
152 # a revision we have to only delete the bookmark and not strip |
200 # a revision we have to only delete the bookmark and not strip |
153 # anything. revsets cannot detect that case. |
201 # anything. revsets cannot detect that case. |
154 nodetobookmarks = {} |
202 nodetobookmarks = {} |
172 strippedrevs = revs.union(descendants) |
220 strippedrevs = revs.union(descendants) |
173 roots = revs.difference(descendants) |
221 roots = revs.difference(descendants) |
174 |
222 |
175 # if one of the wdir parent is stripped we'll need |
223 # if one of the wdir parent is stripped we'll need |
176 # to update away to an earlier revision |
224 # to update away to an earlier revision |
177 update = any(p != nullid and cl.rev(p) in strippedrevs |
225 update = any( |
178 for p in repo.dirstate.parents()) |
226 p != nullid and cl.rev(p) in strippedrevs |
|
227 for p in repo.dirstate.parents() |
|
228 ) |
179 |
229 |
180 rootnodes = set(cl.node(r) for r in roots) |
230 rootnodes = set(cl.node(r) for r in roots) |
181 |
231 |
182 q = getattr(repo, 'mq', None) |
232 q = getattr(repo, 'mq', None) |
183 if q is not None and q.applied: |
233 if q is not None and q.applied: |