Mercurial > public > mercurial-scm > hg
comparison mercurial/patch.py @ 14350:00da6624e167
patch: move copyfile() into backends, abstract basedir
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Tue, 17 May 2011 23:46:38 +0200 |
parents | 776ae95b8835 |
children | d54f9bbcc640 |
comparison
equal
deleted
inserted
replaced
14349:776ae95b8835 | 14350:00da6624e167 |
---|---|
16 gitre = re.compile('diff --git a/(.*) b/(.*)') | 16 gitre = re.compile('diff --git a/(.*) b/(.*)') |
17 | 17 |
18 class PatchError(Exception): | 18 class PatchError(Exception): |
19 pass | 19 pass |
20 | 20 |
21 # helper functions | |
22 | |
23 def copyfile(src, dst, basedir): | |
24 abssrc, absdst = [scmutil.canonpath(basedir, basedir, x) | |
25 for x in [src, dst]] | |
26 if os.path.lexists(absdst): | |
27 raise util.Abort(_("cannot create %s: destination already exists") % | |
28 dst) | |
29 | |
30 dstdir = os.path.dirname(absdst) | |
31 if dstdir and not os.path.isdir(dstdir): | |
32 try: | |
33 os.makedirs(dstdir) | |
34 except IOError: | |
35 raise util.Abort( | |
36 _("cannot create %s: unable to create destination directory") | |
37 % dst) | |
38 | |
39 util.copyfile(abssrc, absdst) | |
40 | 21 |
41 # public functions | 22 # public functions |
42 | 23 |
43 def split(stream): | 24 def split(stream): |
44 '''return an iterator of individual patches from a stream''' | 25 '''return an iterator of individual patches from a stream''' |
404 which failed to apply and total the total number of hunks for this | 385 which failed to apply and total the total number of hunks for this |
405 files. | 386 files. |
406 """ | 387 """ |
407 pass | 388 pass |
408 | 389 |
390 def copy(self, src, dst): | |
391 """Copy src file into dst file. Create intermediate directories if | |
392 necessary. Files are specified relatively to the patching base | |
393 directory. | |
394 """ | |
395 raise NotImplementedError | |
396 | |
409 class fsbackend(abstractbackend): | 397 class fsbackend(abstractbackend): |
410 def __init__(self, ui, opener): | 398 def __init__(self, ui, basedir): |
411 super(fsbackend, self).__init__(ui) | 399 super(fsbackend, self).__init__(ui) |
412 self.opener = opener | 400 self.opener = scmutil.opener(basedir) |
413 | 401 |
414 def readlines(self, fname): | 402 def readlines(self, fname): |
415 if os.path.islink(fname): | 403 if os.path.islink(fname): |
416 return [os.readlink(fname)] | 404 return [os.readlink(fname)] |
417 fp = self.opener(fname, 'r') | 405 fp = self.opener(fname, 'r') |
453 _("%d out of %d hunks FAILED -- saving rejects to file %s\n") % | 441 _("%d out of %d hunks FAILED -- saving rejects to file %s\n") % |
454 (failed, total, fname)) | 442 (failed, total, fname)) |
455 fp = self.opener(fname, 'w') | 443 fp = self.opener(fname, 'w') |
456 fp.writelines(lines) | 444 fp.writelines(lines) |
457 fp.close() | 445 fp.close() |
446 | |
447 def copy(self, src, dst): | |
448 basedir = self.opener.base | |
449 abssrc, absdst = [scmutil.canonpath(basedir, basedir, x) | |
450 for x in [src, dst]] | |
451 if os.path.lexists(absdst): | |
452 raise util.Abort(_("cannot create %s: destination already exists") | |
453 % dst) | |
454 dstdir = os.path.dirname(absdst) | |
455 if dstdir and not os.path.isdir(dstdir): | |
456 try: | |
457 os.makedirs(dstdir) | |
458 except IOError: | |
459 raise util.Abort( | |
460 _("cannot create %s: unable to create destination directory") | |
461 % dst) | |
462 util.copyfile(abssrc, absdst) | |
458 | 463 |
459 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1 | 464 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1 |
460 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@') | 465 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@') |
461 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)') | 466 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)') |
462 eolmodes = ['strict', 'crlf', 'lf', 'auto'] | 467 eolmodes = ['strict', 'crlf', 'lf', 'auto'] |
1145 patching then normalized according to 'eolmode'. | 1150 patching then normalized according to 'eolmode'. |
1146 | 1151 |
1147 Callers probably want to call '_updatedir' after this to | 1152 Callers probably want to call '_updatedir' after this to |
1148 apply certain categories of changes not done by this function. | 1153 apply certain categories of changes not done by this function. |
1149 """ | 1154 """ |
1150 return _applydiff(ui, fp, patchfile, copyfile, changed, strip=strip, | 1155 return _applydiff(ui, fp, patchfile, changed, strip=strip, |
1151 eolmode=eolmode) | 1156 eolmode=eolmode) |
1152 | 1157 |
1153 def _applydiff(ui, fp, patcher, copyfn, changed, strip=1, eolmode='strict'): | 1158 def _applydiff(ui, fp, patcher, changed, strip=1, eolmode='strict'): |
1154 rejects = 0 | 1159 rejects = 0 |
1155 err = 0 | 1160 err = 0 |
1156 current_file = None | 1161 current_file = None |
1157 cwd = os.getcwd() | 1162 cwd = os.getcwd() |
1158 backend = fsbackend(ui, scmutil.opener(cwd)) | 1163 backend = fsbackend(ui, os.getcwd()) |
1159 | 1164 |
1160 for state, values in iterhunks(fp): | 1165 for state, values in iterhunks(fp): |
1161 if state == 'hunk': | 1166 if state == 'hunk': |
1162 if not current_file: | 1167 if not current_file: |
1163 continue | 1168 continue |
1186 if gp.oldpath: | 1191 if gp.oldpath: |
1187 gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1] | 1192 gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1] |
1188 # Binary patches really overwrite target files, copying them | 1193 # Binary patches really overwrite target files, copying them |
1189 # will just make it fails with "target file exists" | 1194 # will just make it fails with "target file exists" |
1190 if gp.op in ('COPY', 'RENAME') and not gp.binary: | 1195 if gp.op in ('COPY', 'RENAME') and not gp.binary: |
1191 copyfn(gp.oldpath, gp.path, cwd) | 1196 backend.copy(gp.oldpath, gp.path) |
1192 changed[gp.path] = gp | 1197 changed[gp.path] = gp |
1193 else: | 1198 else: |
1194 raise util.Abort(_('unsupported parser state: %s') % state) | 1199 raise util.Abort(_('unsupported parser state: %s') % state) |
1195 | 1200 |
1196 if current_file: | 1201 if current_file: |