[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