def runPatcher(self, fp, wfile, updatestate): ui = self.repo.ui.copy() class warncapt(ui.__class__): def warn(self, msg, *args, **opts): self.write(msg) ui.__class__ = warncapt ok = True repo = self.repo ui.pushbuffer() try: eolmode = ui.config('patch', 'eol', 'strict') if eolmode.lower() not in patch.eolmodes: eolmode = 'strict' else: eolmode = eolmode.lower() try: # hg-1.9 ret = patch.internalpatch(ui, repo, fp, 1, files=None, eolmode=eolmode, similarity=0) except TypeError: # hg-1.8 pfiles = {} ret = patch.internalpatch(fp, ui, 1, repo.root, pfiles, eolmode=eolmode) if updatestate: cmdutil.updatedir(repo.ui, repo, pfiles) if ret < 0: ok = False self.showMessage.emit(_('Patch failed to apply')) except (patch.PatchError, EnvironmentError), err: ok = False self.showMessage.emit(hglib.tounicode(str(err)))
def updatedir(*args, **kwargs): # updatedir moved from patch to cmdutil in hg 1.7 if hasattr(patch, 'updatedir'): patch.updatedir(*args, **kwargs) elif hasattr(cmdutil, 'updatedir'): cmdutil.updatedir(*args, **kwargs) else: # hg 1.9+ moved updatedir, and more importantly it's not needed with the way patch is called now.. scmutil.updatedir(*args, **kwargs)
def unshelve(ui, repo, *pats, **opts): '''restore shelved changes''' try: fp = cStringIO.StringIO() fp.write(repo.opener('shelve').read()) except: ui.warn(_('nothing to unshelve\n')) else: if opts['inspect']: ui.status(fp.getvalue()) else: files = [] fp.seek(0) for chunk in parsepatch(fp): if isinstance(chunk, header): files += chunk.files() backupdir = repo.join('shelve-backups') try: backups = makebackup(ui, repo, backupdir, set(files)) except: ui.warn(_('unshelve backup aborted\n')) delete_backup(ui, repo, backupdir) raise ui.debug(_('applying shelved patch\n')) patchdone = 0 try: try: fp.seek(0) pfiles = {} internalpatch(fp, ui, 1, repo.root, files=pfiles) cmdutil.updatedir(ui, repo, pfiles) patchdone = 1 except: if opts['force']: patchdone = 1 else: ui.status(_('restoring backup files\n')) for realname, tmpname in backups.iteritems(): ui.debug(_('restoring %r to %r\n') % (tmpname, realname)) util.copyfile(tmpname, repo.wjoin(realname)) finally: delete_backup(ui, repo, backupdir) if patchdone: ui.debug(_('removing shelved patches\n')) os.unlink(repo.join('shelve')) ui.status(_('unshelve completed\n')) else: raise patch.PatchError
def pick(ui, repo, ctx, ha, opts): oldctx = repo[ha] if oldctx.parents()[0] == ctx: ui.debug('node %s unchanged\n' % ha) return oldctx, [], [], [] hg.update(repo, ctx.node()) fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-') fp = os.fdopen(fd, 'w') diffopts = patch.diffopts(ui, opts) diffopts.git = True diffopts.ignorews = False diffopts.ignorewsamount = False diffopts.ignoreblanklines = False gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts) for chunk in gen: fp.write(chunk) fp.close() try: files = {} try: patch.patch(patchfile, ui, cwd=repo.root, files=files, eolmode=None) if not files: ui.warn(_('%s: empty changeset') % node.hex(ha)) return ctx, [], [], [] finally: files = updatedir(ui, repo, files) os.unlink(patchfile) except Exception, inst: raise util.Abort(_('Fix up the change and run ' 'hg histedit --continue'))
def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges): parent = ctx.parents()[0].node() hg.update(repo, parent) fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-') fp = os.fdopen(fd, 'w') diffopts = patch.diffopts(ui, opts) diffopts.git = True diffopts.ignorews = False diffopts.ignorewsamount = False diffopts.ignoreblanklines = False gen = patch.diff(repo, parent, newnode, opts=diffopts) for chunk in gen: fp.write(chunk) fp.close() files = {} try: patch.patch(patchfile, ui, cwd=repo.root, files=files, eolmode=None) finally: files = updatedir(ui, repo, files) os.unlink(patchfile) newmessage = '\n***\n'.join( [ctx.description(), ] + [repo[r].description() for r in internalchanges] + [oldctx.description(), ]) newmessage = ui.edit(newmessage, ui.username()) n = repo.commit(text=newmessage, user=ui.username(), date=max(ctx.date(), oldctx.date()), extra=oldctx.extra()) return repo[n], [n, ], [oldctx.node(), ctx.node() ], [newnode, ] # xxx
def runPatcher(self, fp, wfile, updatestate): ui = self.repo.ui.copy() class warncapt(ui.__class__): def warn(self, msg, *args, **opts): self.write(msg) ui.__class__ = warncapt ok = True repo = self.repo ui.pushbuffer() try: eolmode = ui.config('patch', 'eol', 'strict') if eolmode.lower() not in patch.eolmodes: eolmode = 'strict' else: eolmode = eolmode.lower() try: # hg-1.9 ret = patch.internalpatch(ui, repo, fp, 1, files=None, eolmode=eolmode, similarity=0) except TypeError: # hg-1.8 pfiles = {} ret = patch.internalpatch(fp, ui, 1, repo.root, pfiles, eolmode=eolmode) if updatestate: cmdutil.updatedir(repo.ui, repo, pfiles) except ValueError: ret = -1 if ret < 0: ok = False self.showMessage.emit(_('Patch failed to apply')) except (patch.PatchError, EnvironmentError), err: ok = False self.showMessage.emit(hglib.tounicode(str(err)))
def applyone(self, repo, node, cl, patchfile, merge=False, log=False, filter=None): '''apply the patch in patchfile to the repository as a transplant''' (manifest, user, (time, timezone), files, message) = cl[:5] date = "%d %d" % (time, timezone) extra = {'transplant_source': node} if filter: (user, date, message) = self.filter(filter, cl, patchfile) if log: # we don't translate messages inserted into commits message += '\n(transplanted from %s)' % revlog.hex(node) self.ui.status(_('applying %s\n') % revlog.short(node)) self.ui.note('%s %s\n%s\n' % (user, date, message)) if not patchfile and not merge: raise util.Abort(_('can only omit patchfile if merging')) if patchfile: try: files = {} try: patch.patch(patchfile, self.ui, cwd=repo.root, files=files, eolmode=None) if not files: self.ui.warn( _('%s: empty changeset') % revlog.hex(node)) return None finally: files = cmdutil.updatedir(self.ui, repo, files) except Exception, inst: seriespath = os.path.join(self.path, 'series') if os.path.exists(seriespath): os.unlink(seriespath) p1 = repo.dirstate.parents()[0] p2 = node self.log(user, date, message, p1, p2, merge=merge) self.ui.write(str(inst) + '\n') raise util.Abort( _('fix up the merge and run ' 'hg transplant --continue'))
def applyone(self, repo, node, cl, patchfile, merge=False, log=False, filter=None): '''apply the patch in patchfile to the repository as a transplant''' (manifest, user, (time, timezone), files, message) = cl[:5] date = "%d %d" % (time, timezone) extra = {'transplant_source': node} if filter: (user, date, message) = self.filter(filter, cl, patchfile) if log: # we don't translate messages inserted into commits message += '\n(transplanted from %s)' % revlog.hex(node) self.ui.status(_('applying %s\n') % revlog.short(node)) self.ui.note('%s %s\n%s\n' % (user, date, message)) if not patchfile and not merge: raise util.Abort(_('can only omit patchfile if merging')) if patchfile: try: files = {} try: patch.patch(patchfile, self.ui, cwd=repo.root, files=files, eolmode=None) if not files: self.ui.warn(_('%s: empty changeset') % revlog.hex(node)) return None finally: files = cmdutil.updatedir(self.ui, repo, files) except Exception, inst: seriespath = os.path.join(self.path, 'series') if os.path.exists(seriespath): os.unlink(seriespath) p1 = repo.dirstate.parents()[0] p2 = node self.log(user, date, message, p1, p2, merge=merge) self.ui.write(str(inst) + '\n') raise util.Abort(_('fix up the merge and run ' 'hg transplant --continue'))
def edit(ui, repo, ctx, ha, opts): oldctx = repo[ha] hg.update(repo, ctx.node()) fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-') fp = os.fdopen(fd, 'w') diffopts = patch.diffopts(ui, opts) diffopts.git = True diffopts.ignorews = False diffopts.ignorewsamount = False diffopts.ignoreblanklines = False gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts) for chunk in gen: fp.write(chunk) fp.close() try: files = {} try: patch.patch(patchfile, ui, cwd=repo.root, files=files, eolmode=None) finally: files = updatedir(ui, repo, files) os.unlink(patchfile) except Exception, inst: pass
def updatedir(*args, **kwargs): # updatedir moved from patch to cmdutil in hg 1.7 if hasattr(patch, 'updatedir'): patch.updatedir(*args, **kwargs) else: cmdutil.updatedir(*args, **kwargs)
def dorecord(ui, repo, commitfunc, *pats, **opts): try: if not ui.interactive(): raise util.Abort(_('running non-interactively, use commit instead')) except TypeError: # backwards compatibility with hg 1.1 if not ui.interactive: raise util.Abort(_('running non-interactively, use commit instead')) def recordfunc(ui, repo, message, match, opts): """This is generic record driver. Its job is to interactively filter local changes, and accordingly prepare working dir into a state, where the job can be delegated to non-interactive commit command such as 'commit' or 'qrefresh'. After the actual job is done by non-interactive command, working dir state is restored to original. In the end we'll record interesting changes, and everything else will be left in place, so the user can continue his work. """ merge = len(repo[None].parents()) > 1 if merge: raise util.Abort(_('cannot partially commit a merge ' '(use hg commit instead)')) # status gives back # modified, added, removed, deleted, unknown, ignored, clean # we take only the first 3 of these changes = repo.status(match=match)[:3] modified, added, removed = changes diffopts = opts.copy() diffopts['nodates'] = True diffopts['git'] = True diffopts = patch.diffopts(ui, opts=diffopts) chunks = patch.diff(repo, changes=changes, opts=diffopts) fp = cStringIO.StringIO() fp.write(''.join(chunks)) fp.seek(0) # 1. filter patch, so we have intending-to apply subset of it chunks = crpatch.filterpatch(opts, crpatch.parsepatch(changes, fp), chunk_selector.chunkselector, ui) del fp contenders = set() for h in chunks: try: contenders.update(set(h.files())) except AttributeError: pass changed = changes[0] + changes[1] + changes[2] newfiles = [f for f in changed if f in contenders] if not newfiles: ui.status(_('no changes to record\n')) return 0 # 2. backup changed files, so we can restore them in the end backups = {} newly_added_backups = {} backupdir = repo.join('record-backups') try: os.mkdir(backupdir) except OSError, err: if err.errno != errno.EEXIST: raise try: # backup continues for f in newfiles: if f not in (modified + added): continue fd, tmpname = tempfile.mkstemp(prefix=f.replace('/', '_')+'.', dir=backupdir) os.close(fd) ui.debug('backup %r as %r\n' % (f, tmpname)) util.copyfile(repo.wjoin(f), tmpname) if f in modified: backups[f] = tmpname elif f in added: newly_added_backups[f] = tmpname fp = cStringIO.StringIO() all_backups = {} all_backups.update(backups) all_backups.update(newly_added_backups) for c in chunks: if c.filename() in all_backups: c.write(fp) dopatch = fp.tell() fp.seek(0) # 2.5 optionally review / modify patch in text editor if opts['crecord_reviewpatch']: patchtext = fp.read() reviewedpatch = ui.edit(patchtext, "") fp.truncate(0) fp.write(reviewedpatch) fp.seek(0) # 3a. apply filtered patch to clean repo (clean) if backups: hg.revert(repo, repo.dirstate.parents()[0], lambda key: key in backups) # remove newly added files from 'clean' repo (so patch can apply) for f in newly_added_backups: os.unlink(f) # 3b. (apply) if dopatch: try: ui.debug('applying patch\n') ui.debug(fp.getvalue()) if hasattr(patch, 'workingbackend'): # detect 1.9 patch.internalpatch(ui, repo, fp, strip=1, eolmode=None) else: pfiles = {} try: patch.internalpatch(ui, repo, fp, 1, eolmode=None) except (TypeError, AttributeError): # pre 17cea10c343e try: patch.internalpatch(ui, repo, fp, 1, repo.root, eolmode=None) except (TypeError, AttributeError): # pre 00a881581400 try: patch.internalpatch(fp, ui, 1, repo.root, files=pfiles, eolmode=None) except TypeError: # backwards compatible with hg 1.1 patch.internalpatch(fp, ui, 1, repo.root, files=pfiles) try: cmdutil.updatedir(ui, repo, pfiles) except AttributeError: try: patch.updatedir(ui, repo, pfiles) except AttributeError: # from 00a881581400 onwards pass except patch.PatchError, err: s = str(err) if s: raise util.Abort(s) else: raise util.Abort(_('patch failed to apply')) del fp # 4. We prepared working directory according to filtered patch. # Now is the time to delegate the job to commit/qrefresh or the like! # it is important to first chdir to repo root -- we'll call a # highlevel command with list of pathnames relative to repo root newfiles = [repo.wjoin(n) for n in newfiles] commitfunc(ui, repo, *newfiles, **opts) return 0
def dorecord(ui, repo, commitfunc, *pats, **opts): if not ui.interactive(): raise util.Abort(_('running non-interactively, use commit instead')) def recordfunc(ui, repo, message, match, opts): """This is generic record driver. Its job is to interactively filter local changes, and accordingly prepare working directory into a state in which the job can be delegated to a non-interactive commit command such as 'commit' or 'qrefresh'. After the actual job is done by non-interactive command, the working directory is restored to its original state. In the end we'll record interesting changes, and everything else will be left in place, so the user can continue working. """ merge = len(repo[None].parents()) > 1 if merge: raise util.Abort( _('cannot partially commit a merge ' '(use "hg commit" instead)')) changes = repo.status(match=match)[:3] diffopts = mdiff.diffopts(git=True, nodates=True) chunks = patch.diff(repo, changes=changes, opts=diffopts) fp = cStringIO.StringIO() fp.write(''.join(chunks)) fp.seek(0) # 1. filter patch, so we have intending-to apply subset of it chunks = filterpatch(ui, parsepatch(fp)) del fp contenders = set() for h in chunks: try: contenders.update(set(h.files())) except AttributeError: pass changed = changes[0] + changes[1] + changes[2] newfiles = [f for f in changed if f in contenders] if not newfiles: ui.status(_('no changes to record\n')) return 0 modified = set(changes[0]) # 2. backup changed files, so we can restore them in the end backups = {} backupdir = repo.join('record-backups') try: os.mkdir(backupdir) except OSError, err: if err.errno != errno.EEXIST: raise try: # backup continues for f in newfiles: if f not in modified: continue fd, tmpname = tempfile.mkstemp(prefix=f.replace('/', '_') + '.', dir=backupdir) os.close(fd) ui.debug('backup %r as %r\n' % (f, tmpname)) util.copyfile(repo.wjoin(f), tmpname) shutil.copystat(repo.wjoin(f), tmpname) backups[f] = tmpname fp = cStringIO.StringIO() for c in chunks: if c.filename() in backups: c.write(fp) dopatch = fp.tell() fp.seek(0) # 3a. apply filtered patch to clean repo (clean) if backups: hg.revert(repo, repo.dirstate.parents()[0], lambda key: key in backups) # 3b. (apply) if dopatch: try: ui.debug('applying patch\n') ui.debug(fp.getvalue()) pfiles = {} patch.internalpatch(fp, ui, 1, repo.root, files=pfiles, eolmode=None) cmdutil.updatedir(ui, repo, pfiles) except patch.PatchError, err: raise util.Abort(str(err)) del fp # 4. We prepared working directory according to filtered # patch. Now is the time to delegate the job to # commit/qrefresh or the like! # it is important to first chdir to repo root -- we'll call # a highlevel command with list of pathnames relative to # repo root cwd = os.getcwd() os.chdir(repo.root) try: commitfunc(ui, repo, *newfiles, **opts) finally: os.chdir(cwd) return 0
time.sleep(1) files = {} try: diff = self.bu.backupfile('diff') try: fuzz = patch.patch(diff, self.ws.ui, strip=1, cwd=self.ws.repo.root, files=files) if fuzz: raise util.Abort('working copy diff applied with fuzz') except Exception, e: raise util.Abort("couldn't apply working copy diff: %s\n" " %s" % (diff, e)) finally: if Version.at_least("1.7"): cmdutil.updatedir(self.ws.ui, self.ws.repo, files) else: patch.updatedir(self.ws.ui, self.ws.repo, files) if not self.bu.exists('renames'): return # # We need to re-apply name changes where the new name # (rename/copy destination) is an already versioned file, as # Hg would otherwise ignore them. # try: fp = self.bu.open('renames') for line in fp: source, dest = line.strip().split()
def updatedir(*args, **kwargs): # updatedir moved from patch to cmdutil in hg 1.7 if hasattr(patch, 'updatedir'): patch.updatedir(*args, **kwargs) else: cmdutil.updatedir(*args, **kwargs)
def dorecord(ui, repo, commitfunc, *pats, **opts): if not ui.interactive(): raise util.Abort(_('running non-interactively, use commit instead')) def recordfunc(ui, repo, message, match, opts): """This is generic record driver. Its job is to interactively filter local changes, and accordingly prepare working directory into a state in which the job can be delegated to a non-interactive commit command such as 'commit' or 'qrefresh'. After the actual job is done by non-interactive command, the working directory is restored to its original state. In the end we'll record interesting changes, and everything else will be left in place, so the user can continue working. """ merge = len(repo[None].parents()) > 1 if merge: raise util.Abort(_('cannot partially commit a merge ' '(use "hg commit" instead)')) changes = repo.status(match=match)[:3] diffopts = mdiff.diffopts(git=True, nodates=True) chunks = patch.diff(repo, changes=changes, opts=diffopts) fp = cStringIO.StringIO() fp.write(''.join(chunks)) fp.seek(0) # 1. filter patch, so we have intending-to apply subset of it chunks = filterpatch(ui, parsepatch(fp)) del fp contenders = set() for h in chunks: try: contenders.update(set(h.files())) except AttributeError: pass changed = changes[0] + changes[1] + changes[2] newfiles = [f for f in changed if f in contenders] if not newfiles: ui.status(_('no changes to record\n')) return 0 modified = set(changes[0]) # 2. backup changed files, so we can restore them in the end backups = {} backupdir = repo.join('record-backups') try: os.mkdir(backupdir) except OSError, err: if err.errno != errno.EEXIST: raise try: # backup continues for f in newfiles: if f not in modified: continue fd, tmpname = tempfile.mkstemp(prefix=f.replace('/', '_')+'.', dir=backupdir) os.close(fd) ui.debug('backup %r as %r\n' % (f, tmpname)) util.copyfile(repo.wjoin(f), tmpname) shutil.copystat(repo.wjoin(f), tmpname) backups[f] = tmpname fp = cStringIO.StringIO() for c in chunks: if c.filename() in backups: c.write(fp) dopatch = fp.tell() fp.seek(0) # 3a. apply filtered patch to clean repo (clean) if backups: hg.revert(repo, repo.dirstate.parents()[0], lambda key: key in backups) # 3b. (apply) if dopatch: try: ui.debug('applying patch\n') ui.debug(fp.getvalue()) pfiles = {} patch.internalpatch(fp, ui, 1, repo.root, files=pfiles, eolmode=None) cmdutil.updatedir(ui, repo, pfiles) except patch.PatchError, err: raise util.Abort(str(err)) del fp # 4. We prepared working directory according to filtered # patch. Now is the time to delegate the job to # commit/qrefresh or the like! # it is important to first chdir to repo root -- we'll call # a highlevel command with list of pathnames relative to # repo root cwd = os.getcwd() os.chdir(repo.root) try: commitfunc(ui, repo, *newfiles, **opts) finally: os.chdir(cwd) return 0