Search code examples
mercurialmercurial-revsets

Is there a Mercurial revset for "working directory"?


I'm trying to script hg diff and want to accept an argument that will be passed to the -r option, and if no argument is given, to default to the working directory. However, it appears there is no value that can be passed to -r to indicate "working directory", and instead the option must be omitted entirely, which leads to the following logic in my script:

if [ -z "${to_rev}" ]; then
  to_rev_args=""
else
  to_rev_args="-r ${to_rev}"
fi

hg diff ... ${to_rev_args}

Am I correct in believing this is the only way? We can assume that making the script accept a -r argument and passing the whole thing on to Mercurial is not an option; the arguments must conform to a style used by a suite of tools.


Solution

  • The following Mercurial extension should do what you need, by allowing you to specify the working directory as a pseudo revision named "=".

    """wdir diff
    
    Allows specifying the working directory as a pseudo revision.
    """
    
    testedwith = "3.5"
    wdir_pseudo_rev = "="
    
    from mercurial import commands, extensions
    
    def wrap_diff(original_cmd, ui, repo, *pats, **opts):
      revargs = opts["rev"]
      if len(revargs) == 1:
        if revargs[0] == wdir_pseudo_rev:
          return
      elif len(revargs) == 2:
        if revargs[0] == wdir_pseudo_rev:
          if revargs[1] == wdir_pseudo_rev:
            return
          else:
            revargs.remove(wdir_pseudo_rev)
        elif revargs[1] == wdir_pseudo_rev:
          revargs.remove(wdir_pseudo_rev)
          opts["reverse"] = not opts["reverse"]
      return original_cmd(ui, repo, *pats, **opts)
    
    def uisetup(ui):
      extensions.wrapcommand(commands.table, "diff", wrap_diff)
    

    The same logic can also fairly easily be encoded in a script or other program code if you don't want the hassle of dealing with an extension, you just have to distinguish between four different cases:

    Assume that you want to diff REV1 and REV2, where either revision may be the working directory:

    1. If both REV1 and REV2 represent the working directory, do nothing.
    2. If REV1 represents the working directory, and REV2 is an actual revision, use hg diff -r REV2.
    3. If REV1 is an actual revision, and REV2 represents the working directory, use hg diff --reverse -r REV1.
    4. If both REV1 and REV2 are actual revisions, use hg diff -r REV1 -r REV2.