comparison hgext/evolve.py @ 1058:00bc31523074

uncommit: add a --rev argument The uncommit command now taks a --rev argument. This lets restore the file content in the current commit to another revision (instead of just is parent content). This still does not touch the working directory content.\ This allow the longly awaited: hg uncommit --hidden --rev 'precursors(.)'
author Pierre-Yves David <pierre-yves.david@fb.com>
date Fri, 15 Aug 2014 00:46:23 -0700
parents cfe1b9d3e5d9
children 742c1ce79a96
comparison
equal deleted inserted replaced
1056:edfb9a0ad085 1058:00bc31523074
1857 opts['message'] = repo['.'].description() 1857 opts['message'] = repo['.'].description()
1858 _resolveoptions(ui, opts) 1858 _resolveoptions(ui, opts)
1859 _alias, commitcmd = cmdutil.findcmd('commit', commands.table) 1859 _alias, commitcmd = cmdutil.findcmd('commit', commands.table)
1860 return commitcmd[0](ui, repo, *pats, **opts) 1860 return commitcmd[0](ui, repo, *pats, **opts)
1861 1861
1862 def _commitfiltered(repo, ctx, match): 1862
1863 def _touchedbetween(repo, source, dest, match=None):
1864 touched = set()
1865 for files in repo.status(source, dest, match=match)[:3]:
1866 touched.update(files)
1867 return touched
1868
1869 def _commitfiltered(repo, ctx, match, target=None):
1863 """Recommit ctx with changed files not in match. Return the new 1870 """Recommit ctx with changed files not in match. Return the new
1864 node identifier, or None if nothing changed. 1871 node identifier, or None if nothing changed.
1865 """ 1872 """
1866 base = ctx.p1() 1873 base = ctx.p1()
1867 m, a, r = repo.status(base, ctx)[:3] 1874 if target is None:
1868 allfiles = set(m + a + r) 1875 target = base
1869 files = set(f for f in allfiles if not match(f)) 1876 # ctx
1870 if files == allfiles: 1877 initialfiles = _touchedbetween(repo, base, ctx)
1878 if base == target:
1879 affected = set(f for f in initialfiles if match(f))
1880 newcontent = set()
1881 else:
1882 affected = _touchedbetween(repo, target, ctx, match=match)
1883 newcontent = _touchedbetween(repo, target, base, match=match)
1884 # The commit touchs all existing files
1885 # + all file that needs a new content
1886 # - the file affected bny uncommit with the same content than base.
1887 files = (initialfiles - affected) | newcontent
1888 if not newcontent and files == initialfiles:
1871 return None 1889 return None
1872 1890
1873 # Filter copies 1891 # Filter copies
1874 copied = copies.pathcopies(base, ctx) 1892 copied = copies.pathcopies(target, ctx)
1875 copied = dict((src, dst) for src, dst in copied.iteritems() 1893 copied = dict((src, dst) for src, dst in copied.iteritems()
1876 if dst in files) 1894 if dst in files)
1877 def filectxfn(repo, memctx, path): 1895 def filectxfn(repo, memctx, path, contentctx=ctx, redirect=newcontent):
1878 if path not in ctx: 1896 if path in redirect:
1897 return filectxfn(repo, memctx, path, contentctx=target, redirect=())
1898 if path not in contentctx:
1879 raise IOError() 1899 raise IOError()
1880 fctx = ctx[path] 1900 fctx = contentctx[path]
1881 flags = fctx.flags() 1901 flags = fctx.flags()
1882 mctx = memfilectx(repo, fctx.path(), fctx.data(), 1902 mctx = memfilectx(repo, fctx.path(), fctx.data(),
1883 islink='l' in flags, 1903 islink='l' in flags,
1884 isexec='x' in flags, 1904 isexec='x' in flags,
1885 copied=copied.get(path)) 1905 copied=copied.get(path))
1941 src = None 1961 src = None
1942 ds.copy(src, dst) 1962 ds.copy(src, dst)
1943 1963
1944 @command('^uncommit', 1964 @command('^uncommit',
1945 [('a', 'all', None, _('uncommit all changes when no arguments given')), 1965 [('a', 'all', None, _('uncommit all changes when no arguments given')),
1966 ('r', 'rev', '', _('revert commit content to REV instead')),
1946 ] + commands.walkopts, 1967 ] + commands.walkopts,
1947 _('[OPTION]... [NAME]')) 1968 _('[OPTION]... [NAME]'))
1948 def uncommit(ui, repo, *pats, **opts): 1969 def uncommit(ui, repo, *pats, **opts):
1949 """move changes from parent revision to working directory 1970 """move changes from parent revision to working directory
1950 1971
1953 without the selected changes is created, becomes the checked out 1974 without the selected changes is created, becomes the checked out
1954 revision, and obsoletes the previous one. 1975 revision, and obsoletes the previous one.
1955 1976
1956 The --include option specifies patterns to uncommit. 1977 The --include option specifies patterns to uncommit.
1957 The --exclude option specifies patterns to keep in the commit. 1978 The --exclude option specifies patterns to keep in the commit.
1979
1980 The --rev argument let you change the commit file to a content of another
1981 revision. It still does not change the content of your file in the working
1982 directory.
1958 1983
1959 Return 0 if changed files are uncommitted. 1984 Return 0 if changed files are uncommitted.
1960 """ 1985 """
1961 1986
1962 wlock = lock = tr = None 1987 wlock = lock = tr = None
1974 if len(old.parents()) > 1: 1999 if len(old.parents()) > 1:
1975 raise util.Abort(_("cannot uncommit merge changeset")) 2000 raise util.Abort(_("cannot uncommit merge changeset"))
1976 oldphase = old.phase() 2001 oldphase = old.phase()
1977 updatebookmarks = _bookmarksupdater(repo, old.node()) 2002 updatebookmarks = _bookmarksupdater(repo, old.node())
1978 2003
2004
2005 rev = None
2006 if opts.get('rev'):
2007 rev = scmutil.revsingle(repo, opts.get('rev'))
2008
1979 # Recommit the filtered changeset 2009 # Recommit the filtered changeset
1980 tr = repo.transaction('uncommit') 2010 tr = repo.transaction('uncommit')
1981 newid = None 2011 newid = None
1982 if (pats or opts.get('include') or opts.get('exclude') 2012 if (pats or opts.get('include') or opts.get('exclude')
1983 or opts.get('all')): 2013 or opts.get('all')):
1984 match = scmutil.match(old, pats, opts) 2014 match = scmutil.match(old, pats, opts)
1985 newid = _commitfiltered(repo, old, match) 2015 newid = _commitfiltered(repo, old, match, target=rev)
1986 if newid is None: 2016 if newid is None:
1987 raise util.Abort(_('nothing to uncommit'), 2017 raise util.Abort(_('nothing to uncommit'),
1988 hint=_("use --all to uncommit all files")) 2018 hint=_("use --all to uncommit all files"))
1989 # Move local changes on filtered changeset 2019 # Move local changes on filtered changeset
1990 createmarkers(repo, [(old, (repo[newid],))]) 2020 createmarkers(repo, [(old, (repo[newid],))])