Mercurial > hg
changeset 5827:0c29977bd7db
record: refactor record into generic record driver
rationale
---------
I'd like to make MQ version of record -- qrecord.
>From the first glance it seemed to be easy -- the task in essence would be to
change call to cmdutil.commit() to something like mq.qrefresh().
As it turned out queue.refresh() and cmdutil.commit() have different semantics
-- cmdutil.commit() first scans for changes and then delegate the actual commit
to lowlevel func. On the other hand queue.refresh() do it all in once, and I am
a bit scary to change it.
Maybe the right way would be to first refactor queue.refresh() to use
cmdutil.commit() machinery, and then trivially adjust record, but I feel I'm
not competent for the task right now.
Instead, I propose we refactor record to be some sort of high-level driver, or
like a high-level decorator one can say, which will first interactively filter
changes, and then delegate commit job to high-level commiter, e.g. 'commit' or
'qrefresh'
So, this patch does just that -- refactor record to be generic driver, and
update 'hg record' code to use the driver.
'hg qrecord' will follow.
author | Kirill Smelkov <kirr@mns.spb.ru> |
---|---|
date | Thu, 10 Jan 2008 12:07:13 +0300 |
parents | cc43d9f36ff2 |
children | 863e237b58fb |
files | hgext/record.py |
diffstat | 1 files changed, 37 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/record.py Thu Jan 10 11:43:30 2008 +0300 +++ b/hgext/record.py Thu Jan 10 12:07:13 2008 +0300 @@ -358,10 +358,29 @@ ? - display help''' + def record_commiter(ui, repo, pats, opts): + commands.commit(ui, repo, *pats, **opts) + + dorecord(ui, repo, record_commiter, *pats, **opts) + + +def dorecord(ui, repo, committer, *pats, **opts): if not ui.interactive: raise util.Abort(_('running non-interactively, use commit instead')) def recordfunc(ui, repo, files, message, match, opts): + """This is generic record driver. + + It's 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 intresting changes, and everything else will be + left in place, so the user can continue his work. + """ if files: changes = None else: @@ -374,6 +393,7 @@ match=match, changes=changes, opts=diffopts, fp=fp) fp.seek(0) + # 1. filter patch, so we have intending-to apply subset of it chunks = filterpatch(ui, parsepatch(fp)) del fp @@ -392,6 +412,7 @@ changes = repo.status(files=newfiles, match=match)[:5] modified = dict.fromkeys(changes[0]) + # 2. backup changed files, so we can restore them in the end backups = {} backupdir = repo.join('record-backups') try: @@ -400,6 +421,7 @@ if err.errno != errno.EEXIST: raise try: + # backup continues for f in newfiles: if f not in modified: continue @@ -417,19 +439,32 @@ dopatch = fp.tell() fp.seek(0) + # 3a. apply filtered patch to clean repo (clean) if backups: hg.revert(repo, repo.dirstate.parents()[0], backups.has_key) + # 3b. (apply) if dopatch: ui.debug('applying patch\n') ui.debug(fp.getvalue()) patch.internalpatch(fp, ui, 1, repo.root) del fp - repo.commit(newfiles, message, opts['user'], opts['date'], match, - force_editor=opts.get('force_editor')) + # 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: + committer(ui, repo, newfiles, opts) + finally: + os.chdir(cwd) + return 0 finally: + # 5. finally restore backed-up files try: for realname, tmpname in backups.iteritems(): ui.debug('restoring %r to %r\n' % (tmpname, realname))