[PATCH] hgext: add smb extension

Kyle Lippincott spectral at pewpew.net
Wed Apr 1 14:59:07 CDT 2015


:( I thought that this was going to implement hg-vss, a DVCS on top of
Visual Source Safe (which is on top of CIFS/SMB).

On Wed, Apr 1, 2015 at 11:28 AM, Sean Farley <sean at farley.io> wrote:

> # HG changeset patch
> # User Sean Farley <sean at farley.io>
> # Date 1427912211 25200
> #      Wed Apr 01 11:16:51 2015 -0700
> # Node ID 35cf765458f06a7651d0e9ba9340d46369741616
> # Parent  1b97cc5d2272c272961cc3e1d738e521af012a40
> hgext: add smb extension
>
> This extension brings the missing component of DVCS to Mercurial: sound
> effects. Who doesn't want the sound of a vine growing when they 'hg log'
> or the
> sound of a warping down a pipe when updating to an ancestor? I'll tell you.
> Nobody.
>
> For reference and a screencast, the extension is hosted at:
>
> https://bitbucket.org/seanfarley/smb
>
> diff --git a/hgext/smb.py b/hgext/smb.py
> new file mode 100644
> --- /dev/null
> +++ b/hgext/smb.py
> @@ -0,0 +1,209 @@
> +import inspect
> +import os
> +import subprocess
> +
> +from mercurial import _
> +from mercurial import commands
> +from mercurial import error
> +from mercurial import extensions
> +from mercurial import dispatch
> +from mercurial import hg
> +from mercurial import obsolete
> +from mercurial import scmutil
> +from mercurial import util
> +
> +######################
> +# audio player methods
> +######################
> +
> +def is_exe(fpath):
> +    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
> +
> +def which(program):
> +    fpath, fname = os.path.split(program)
> +    if fpath:
> +        if is_exe(program):
> +            return program
> +    else:
> +        for path in os.environ["PATH"].split(os.pathsep):
> +            path = path.strip('"')
> +            exe_file = os.path.join(path, program)
> +            if is_exe(exe_file):
> +                return exe_file
> +
> +    return None
> +
> +def audioplayer():
> +    for p in ('afplay', 'aplay', 'mpg123'):
> +        found = which(p)
> +        if found is not None:
> +            return found
> +    return None
> +
> +def play(repo, sound):
> +    if repo is None or not repo.ui.interactive():
> +        return
> +    player = audioplayer()
> +    hasplayed = False
> +    if os.path.exists(repo.join('smbrebasehack')):
> +        os.remove(repo.join('smbrebasehack'))
> +        hasplayed = True
> +
> +    if player and not hasplayed:
> +        datapath = os.path.dirname(os.path.realpath(__file__))
> +        datapath = os.path.join(datapath, 'data')
> +        if not sound.endswith('.wav'):
> +            sound = sound + '.wav'
> +        subprocess.Popen([player, os.path.join(datapath, sound)],
> +                         stdout=open(os.devnull, 'w'),
> +                         stderr=subprocess.STDOUT)
> +
> +##############################
> +# mercurial extension wrappers
> +##############################
> +
> +def extsetup(ui):
> +    extensions.wrapfunction(dispatch, 'runcommand', wrapruncommand)
> +    extensions.wrapfunction(hg, 'updaterepo', wrapupdate)
> +
> +    extensions.wrapcommand(commands.table, 'log', wraplog)
> +    extensions.wrapcommand(commands.table, 'commit', wrapcommit)
> +
> +    try:
> +        rebase = extensions.find('rebase')
> +        if rebase:
> +            extensions.wrapcommand(rebase.cmdtable, 'rebase', wraprebase)
> +    except:
> +        pass
> +
> +    try:
> +        histedit = extensions.find('histedit')
> +        if histedit:
> +            extensions.wrapfunction(histedit, 'finishfold', wrapfold)
> +    except:
> +        pass
> +
> +    try:
> +        purge = extensions.find('purge')
> +        if purge:
> +            extensions.wrapcommand(purge.cmdtable, 'purge', wrappurge)
> +    except:
> +        pass
> +
> +    try:
> +        evolve = extensions.find('evolve')
> +        if evolve:
> +            extensions.wrapcommand(evolve.cmdtable, 'prune', wrapprune)
> +            extensions.wrapcommand(evolve.cmdtable, 'amend', wrapamend)
> +    except:
> +        pass
> +
> +def wrapruncommand(orig, lui, repo, cmd, fullargs, ui, options, d,
> cmdpats,
> +                   cmdoptions):
> +    try:
> +        ret = orig(lui, repo, cmd, fullargs, ui, options, d, cmdpats,
> +                   cmdoptions)
> +        return ret
> +    except Exception as e:
> +        # things to skip:
> +        # - skip if broken pipe (such as quiting from a pager)
> +        # - histedit in progress
> +        if ((not util.safehasattr(e, 'errno') or e.errno != 32)
> +            and e.message != 'histedit in progress'
> +            and e.message != 'rebase in progress'):
> +            if isinstance(e, error.InterventionRequired):
> +                play(repo, 'smb_pause')
> +            else:
> +                play(repo, 'smb_gameover')
> +        raise
> +
> +def wrapupdate(orig, repo, node, overwrite):
> +    # copied from merge.update which should be extracted
> +    wc = repo[None]
> +    p1 = wc.parents()[0]
> +    if node is None:
> +            try:
> +                node = repo.branchtip(wc.branch())
> +            except error.RepoLookupError:
> +                if wc.branch() == 'default':
> +                    node = repo.lookup('tip')
> +                else:
> +                    raise util.Abort(_("branch %s not found") %
> wc.branch())
> +
> +            if p1.obsolete() and not p1.children():
> +                # allow updating to successors
> +                successors = obsolete.successorssets(repo, p1.node())
> +                if successors:
> +                    successors = [n for sub in successors for n in sub]
> +                    node = repo.revs('max(%ln)', successors).first()
> +
> +    current = repo['.']
> +    dest = repo[node]
> +
> +    # things to skip:
> +    # - if current == dest
> +    # - if we are in histedit
> +    # - if we are in a rebase
> +    skip = False
> +    for frame in inspect.stack():
> +        for s in ['rebase', 'hist', 'prune']:
> +            if s in frame[3]:
> +                skip = s
> +        if skip:
> +            break
> +
> +    if current != dest and not skip:
> +        # are we moving from an ancestor to a descendant?
> +        if current.descendant(dest):
> +            play(repo, 'smb_flagpole')
> +        # or from a descendat to ancestor?
> +        elif dest.descendant(current):
> +            play(repo, 'smb_pipe')
> +        # or jumping across branches?
> +        else:
> +            play(repo, 'smb_jump')
> +    return orig(repo, node, overwrite)
> +
> +def wraprebase(orig, ui, repo, **opts):
> +    ret = orig(ui, repo, **opts)
> +    play(repo, 'smb_die')
> +    f = repo.vfs('smbrebasehack', 'w')
> +    f.write("True")
> +    f.close()
> +    return ret
> +
> +def wraplog(orig, ui, repo, *args, **opts):
> +    # double check rev exists so we don't play two sounds
> +    rev = opts.get('rev')
> +    skip = False
> +    if rev and not scmutil.revrange(repo, opts.get('rev')):
> +        skip = True
> +    if not skip:
> +        play(repo, 'smb_vine')
> +    return orig(ui, repo, *args, **opts)
> +
> +def wrapcommit(orig, ui, repo, *args, **opts):
> +    if opts.get('amend'):
> +        play(repo, 'smb_kick')
> +    else:
> +        play(repo, 'smb_1up')
> +    return orig(ui, repo, *args, **opts)
> +
> +def wrapfold(orig, ui, repo, ctx, oldctx, newnode, opts, internalchanges):
> +    play(repo, 'smb_stomp')
> +    return orig(ui, repo, ctx, oldctx, newnode, opts, internalchanges)
> +
> +def wrappurge(orig, ui, repo, *dirs, **opts):
> +    play(repo, 'smb_bowserfire')
> +    return orig(ui, repo, *dirs, **opts)
> +
> +def wrapprune(orig, ui, repo, *revs, **opts):
> +    if opts.get('succ'):
> +        play(repo, 'smb_kick')
> +    else:
> +        play(repo, 'smb_fireball')
> +    return orig(ui, repo, *revs, **opts)
> +
> +def wrapamend(orig, ui, repo, *pats, **opts):
> +    play(repo, 'smb_kick')
> +    return orig(ui, repo, *pats, **opts)
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20150401/f0ab1cdb/attachment.html>


More information about the Mercurial-devel mailing list