88 if f[0] == '/': |
88 if f[0] == '/': |
89 f = f[1:] |
89 f = f[1:] |
90 return filelog.filelog(self.sopener, f, self, self.revlogversion) |
90 return filelog.filelog(self.sopener, f, self, self.revlogversion) |
91 |
91 |
92 def commit(self, files=None, text="", user=None, date=None, |
92 def commit(self, files=None, text="", user=None, date=None, |
93 match=util.always, force=False, lock=None, wlock=None, |
93 match=util.always, force=False, lock=None, wlock=None, |
94 force_editor=False, p1=None, p2=None, extra={}): |
94 force_editor=False, p1=None, p2=None, extra={}): |
95 |
95 |
96 commit = [] |
96 commit = [] |
97 remove = [] |
97 remove = [] |
98 changed = [] |
98 changed = [] |
99 use_dirstate = (p1 is None) # not rawcommit |
99 use_dirstate = (p1 is None) # not rawcommit |
100 extra = extra.copy() |
100 extra = extra.copy() |
101 |
101 |
|
102 if use_dirstate: |
|
103 if files: |
|
104 for f in files: |
|
105 s = self.dirstate.state(f) |
|
106 if s in 'nmai': |
|
107 commit.append(f) |
|
108 elif s == 'r': |
|
109 remove.append(f) |
|
110 else: |
|
111 ui.warn(_("%s not tracked!\n") % f) |
|
112 else: |
|
113 changes = self.status(match=match)[:5] |
|
114 modified, added, removed, deleted, unknown = changes |
|
115 commit = modified + added |
|
116 remove = removed |
|
117 else: |
|
118 commit = files |
|
119 |
|
120 if use_dirstate: |
|
121 p1, p2 = self.dirstate.parents() |
|
122 update_dirstate = True |
|
123 else: |
|
124 p1, p2 = p1, p2 or nullid |
|
125 update_dirstate = (self.dirstate.parents()[0] == p1) |
|
126 |
|
127 c1 = self.changelog.read(p1) |
|
128 c2 = self.changelog.read(p2) |
|
129 m1 = self.manifest.read(c1[0]).copy() |
|
130 m2 = self.manifest.read(c2[0]) |
|
131 |
|
132 if use_dirstate: |
|
133 branchname = self.workingctx().branch() |
|
134 try: |
|
135 branchname = branchname.decode('UTF-8').encode('UTF-8') |
|
136 except UnicodeDecodeError: |
|
137 raise util.Abort(_('branch name not in UTF-8!')) |
|
138 else: |
|
139 branchname = "" |
|
140 |
|
141 if use_dirstate: |
|
142 oldname = c1[5].get("branch", "") # stored in UTF-8 |
|
143 if not commit and not remove and not force and p2 == nullid and \ |
|
144 branchname == oldname: |
|
145 ui.status(_("nothing changed\n")) |
|
146 return None |
|
147 |
|
148 xp1 = hex(p1) |
|
149 if p2 == nullid: xp2 = '' |
|
150 else: xp2 = hex(p2) |
|
151 |
|
152 self.hook("precommit", throw=True, parent1=xp1, parent2=xp2) |
|
153 |
|
154 if not wlock: |
|
155 wlock = self.wlock() |
|
156 if not lock: |
|
157 lock = self.lock() |
|
158 tr = self.transaction() |
|
159 |
|
160 # check in files |
|
161 new = {} |
|
162 linkrev = self.changelog.count() |
|
163 commit.sort() |
|
164 is_exec = util.execfunc(self.root, m1.execf) |
|
165 is_link = util.linkfunc(self.root, m1.linkf) |
|
166 for f in commit: |
|
167 ui.note(f + "\n") |
|
168 try: |
|
169 new[f] = self.filecommit(f, m1, m2, linkrev, tr, changed) |
|
170 m1.set(f, is_exec(f), is_link(f)) |
|
171 except OSError: |
|
172 if use_dirstate: |
|
173 ui.warn(_("trouble committing %s!\n") % f) |
|
174 raise |
|
175 else: |
|
176 remove.append(f) |
|
177 |
|
178 # update manifest |
|
179 m1.update(new) |
|
180 remove.sort() |
|
181 removed = [] |
|
182 |
|
183 for f in remove: |
|
184 if f in m1: |
|
185 del m1[f] |
|
186 removed.append(f) |
|
187 mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0], (new, removed)) |
|
188 |
|
189 # add changeset |
|
190 new = new.keys() |
|
191 new.sort() |
|
192 |
|
193 user = user or ui.username() |
|
194 if not text or force_editor: |
|
195 edittext = [] |
|
196 if text: |
|
197 edittext.append(text) |
|
198 edittext.append("") |
|
199 edittext.append("HG: user: %s" % user) |
|
200 if p2 != nullid: |
|
201 edittext.append("HG: branch merge") |
|
202 edittext.extend(["HG: changed %s" % f for f in changed]) |
|
203 edittext.extend(["HG: removed %s" % f for f in removed]) |
|
204 if not changed and not remove: |
|
205 edittext.append("HG: no files changed") |
|
206 edittext.append("") |
|
207 # run editor in the repository root |
|
208 olddir = os.getcwd() |
|
209 os.chdir(self.root) |
|
210 text = ui.edit("\n".join(edittext), user) |
|
211 os.chdir(olddir) |
|
212 |
|
213 lines = [line.rstrip() for line in text.rstrip().splitlines()] |
|
214 while lines and not lines[0]: |
|
215 del lines[0] |
|
216 if not lines: |
|
217 return None |
|
218 text = '\n'.join(lines) |
|
219 if branchname: |
|
220 extra["branch"] = branchname |
|
221 n = self.changelog.add(mn, changed + removed, text, tr, p1, p2, |
|
222 user, date, extra) |
|
223 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, |
|
224 parent2=xp2) |
|
225 |
|
226 # substitute keywords |
|
227 for f in kwfmatches(ui, self, changed): |
|
228 data = self.wfile(f).read() |
|
229 if not util.binary(data): |
|
230 data, kwct = re_kw.subn(lambda m: |
|
231 kwexpand(m, self, f, changeid=hex(n)), |
|
232 data) |
|
233 if kwct: |
|
234 ui.debug(_('overwriting %s expanding keywords\n' % f)) |
|
235 self.wfile(f, 'w').write(data) |
|
236 |
|
237 tr.close() |
|
238 |
|
239 if use_dirstate or update_dirstate: |
|
240 self.dirstate.setparents(n) |
102 if use_dirstate: |
241 if use_dirstate: |
103 if files: |
242 self.dirstate.update(new, "n") |
104 for f in files: |
243 self.dirstate.forget(removed) |
105 s = self.dirstate.state(f) |
244 |
106 if s in 'nmai': |
245 self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) |
107 commit.append(f) |
246 return n |
108 elif s == 'r': |
|
109 remove.append(f) |
|
110 else: |
|
111 ui.warn(_("%s not tracked!\n") % f) |
|
112 else: |
|
113 changes = self.status(match=match)[:5] |
|
114 modified, added, removed, deleted, unknown = changes |
|
115 commit = modified + added |
|
116 remove = removed |
|
117 else: |
|
118 commit = files |
|
119 |
|
120 if use_dirstate: |
|
121 p1, p2 = self.dirstate.parents() |
|
122 update_dirstate = True |
|
123 else: |
|
124 p1, p2 = p1, p2 or nullid |
|
125 update_dirstate = (self.dirstate.parents()[0] == p1) |
|
126 |
|
127 c1 = self.changelog.read(p1) |
|
128 c2 = self.changelog.read(p2) |
|
129 m1 = self.manifest.read(c1[0]).copy() |
|
130 m2 = self.manifest.read(c2[0]) |
|
131 |
|
132 if use_dirstate: |
|
133 branchname = self.workingctx().branch() |
|
134 try: |
|
135 branchname = branchname.decode('UTF-8').encode('UTF-8') |
|
136 except UnicodeDecodeError: |
|
137 raise util.Abort(_('branch name not in UTF-8!')) |
|
138 else: |
|
139 branchname = "" |
|
140 |
|
141 if use_dirstate: |
|
142 oldname = c1[5].get("branch", "") # stored in UTF-8 |
|
143 if not commit and not remove and not force and p2 == nullid and \ |
|
144 branchname == oldname: |
|
145 ui.status(_("nothing changed\n")) |
|
146 return None |
|
147 |
|
148 xp1 = hex(p1) |
|
149 if p2 == nullid: xp2 = '' |
|
150 else: xp2 = hex(p2) |
|
151 |
|
152 self.hook("precommit", throw=True, parent1=xp1, parent2=xp2) |
|
153 |
|
154 if not wlock: |
|
155 wlock = self.wlock() |
|
156 if not lock: |
|
157 lock = self.lock() |
|
158 tr = self.transaction() |
|
159 |
|
160 # check in files |
|
161 new = {} |
|
162 linkrev = self.changelog.count() |
|
163 commit.sort() |
|
164 is_exec = util.execfunc(self.root, m1.execf) |
|
165 is_link = util.linkfunc(self.root, m1.linkf) |
|
166 for f in commit: |
|
167 ui.note(f + "\n") |
|
168 try: |
|
169 new[f] = self.filecommit(f, m1, m2, linkrev, tr, changed) |
|
170 m1.set(f, is_exec(f), is_link(f)) |
|
171 except OSError: |
|
172 if use_dirstate: |
|
173 ui.warn(_("trouble committing %s!\n") % f) |
|
174 raise |
|
175 else: |
|
176 remove.append(f) |
|
177 |
|
178 # update manifest |
|
179 m1.update(new) |
|
180 remove.sort() |
|
181 removed = [] |
|
182 |
|
183 for f in remove: |
|
184 if f in m1: |
|
185 del m1[f] |
|
186 removed.append(f) |
|
187 mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0], (new, removed)) |
|
188 |
|
189 # add changeset |
|
190 new = new.keys() |
|
191 new.sort() |
|
192 |
|
193 user = user or ui.username() |
|
194 if not text or force_editor: |
|
195 edittext = [] |
|
196 if text: |
|
197 edittext.append(text) |
|
198 edittext.append("") |
|
199 edittext.append("HG: user: %s" % user) |
|
200 if p2 != nullid: |
|
201 edittext.append("HG: branch merge") |
|
202 edittext.extend(["HG: changed %s" % f for f in changed]) |
|
203 edittext.extend(["HG: removed %s" % f for f in removed]) |
|
204 if not changed and not remove: |
|
205 edittext.append("HG: no files changed") |
|
206 edittext.append("") |
|
207 # run editor in the repository root |
|
208 olddir = os.getcwd() |
|
209 os.chdir(self.root) |
|
210 text = ui.edit("\n".join(edittext), user) |
|
211 os.chdir(olddir) |
|
212 |
|
213 lines = [line.rstrip() for line in text.rstrip().splitlines()] |
|
214 while lines and not lines[0]: |
|
215 del lines[0] |
|
216 if not lines: |
|
217 return None |
|
218 text = '\n'.join(lines) |
|
219 if branchname: |
|
220 extra["branch"] = branchname |
|
221 n = self.changelog.add(mn, changed + removed, text, tr, p1, p2, |
|
222 user, date, extra) |
|
223 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, |
|
224 parent2=xp2) |
|
225 |
|
226 # substitute keywords |
|
227 for f in kwfmatches(ui, self, changed): |
|
228 data = self.wfile(f).read() |
|
229 if not util.binary(data): |
|
230 data, kwct = re_kw.subn(lambda m: |
|
231 kwexpand(m, self, f, changeid=hex(n)), |
|
232 data) |
|
233 if kwct: |
|
234 ui.debug(_('overwriting %s expanding keywords\n' |
|
235 % f)) |
|
236 self.wfile(f, 'w').write(data) |
|
237 |
|
238 tr.close() |
|
239 |
|
240 if use_dirstate or update_dirstate: |
|
241 self.dirstate.setparents(n) |
|
242 if use_dirstate: |
|
243 self.dirstate.update(new, "n") |
|
244 self.dirstate.forget(removed) |
|
245 |
|
246 self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) |
|
247 return n |
|
248 |
247 |
249 class kwfilelog(filelog.filelog): |
248 class kwfilelog(filelog.filelog): |
250 def __init__(self, opener, path, repo, |
249 def __init__(self, opener, path, repo, |
251 defversion=revlog.REVLOG_DEFAULT_VERSION): |
250 defversion=revlog.REVLOG_DEFAULT_VERSION): |
252 super(kwfilelog, self).__init__(opener, path, defversion) |
251 super(kwfilelog, self).__init__(opener, path, defversion) |