add "stash" subcommand - fix #1

This commit is contained in:
Josh Holtrop 2012-03-26 11:38:18 -04:00
parent 40775d6d72
commit ce8b679910
2 changed files with 105 additions and 10 deletions

13
README
View File

@ -50,6 +50,19 @@ Implemented subcommands:
- with --status, prepended '*' for those with svn:needs-lock set
externals
- print a list of the externals in the repository
stash [command]
- allow temporarily saving changes to the working copy without committing
- the stashes behaves as a "stack" where "save" pushes a new stash object
and "pop" pops the newest one from the top of the stack
commands:
save (default if not specified):
- save changes as a "stash" object and revert them from working copy
- this currently only works with changes to already-versioned files
list:
- show a list of all stash objects
pop:
- apply the stash object back to the working copy
- the stash object is removed if it was successfully applied
The following subcommands are executed using their native handler, but
have their output simplified and/or colorized:

82
jsvn
View File

@ -52,6 +52,19 @@
# - with --status, prepended '*' for those with svn:needs-lock set
# externals
# - print a list of the externals in the repository
# stash [command]
# - allow temporarily saving changes to the working copy without committing
# - the stashes behaves as a "stack" where "save" pushes a new stash object
# and "pop" pops the newest one from the top of the stack
# commands:
# save (default if not specified):
# - save changes as a "stash" object and revert them from working copy
# - this currently only works with changes to already-versioned files
# list:
# - show a list of all stash objects
# pop:
# - apply the stash object back to the working copy
# - the stash object is removed if it was successfully applied
#
# The following subcommands are executed using their native handler, but
# have their output simplified and/or colorized:
@ -265,6 +278,13 @@ def getSVNRoot(svn):
return '/'.join(parts[:i])
return ''
def get_svn_wc_root(svn):
for line in Popen([svn, 'info'], stdout=PIPE).communicate()[0].split('\n'):
m = re.match(r'Working Copy Root Path: (.*)$', line)
if m is not None:
return m.group(1)
return ''
def getSVNRelPath(svn):
url = getSVNURL(svn)
parts = url.split('/')
@ -373,6 +393,32 @@ def descendant_path(child, parent):
return True
return False
def get_stashes_dir(svn):
stashes_dir = get_svn_wc_root(svn) + '/.svn/stashes'
if not os.path.isdir(stashes_dir):
os.mkdir(stashes_dir)
return stashes_dir
def get_stash_ids(svn):
stashes_dir = get_stashes_dir(svn)
stash_files = os.listdir(stashes_dir)
stash_ids = {}
for sf in stash_files:
m = re.match('stash\.(\d+)$', sf)
if m is not None:
stash_ids[int(m.group(1))] = 1
return sorted(stash_ids.keys())
def get_stash_fname(svn, idx):
return get_stashes_dir(svn) + '/stash.%d' % idx
def get_next_stash_idx(svn):
stash_ids = get_stash_ids(svn)
idx = 1
if len(stash_ids) > 0:
idx = stash_ids[-1] + 1
return idx
###########################################################################
# Subcommand Handlers #
###########################################################################
@ -745,6 +791,41 @@ def externals(argv, svn, out):
out.write(line[8:])
return RET_OK
def stash(argv, svn, out):
action = 'save'
if len(argv) >= 2:
if not argv[1].startswith('-'):
action = argv[1]
if action == 'save':
stash_idx = get_next_stash_idx(svn)
stash_fname = get_stash_fname(svn, stash_idx)
fh = open(stash_fname, 'w')
Popen([svn, 'diff'], stdout=fh).wait()
fh.close()
Popen([svn, 'revert', '--depth=infinity', get_svn_wc_root(svn)],
stdout=PIPE).wait()
out.write('Created stash %d\n' % stash_idx)
elif action == 'list':
stash_ids = get_stash_ids(svn)
for si in reversed(stash_ids):
out.write('%d\n' % si)
elif action == 'pop':
stash_ids = get_stash_ids(svn)
if len(stash_ids) > 0:
stash_idx = stash_ids[-1]
stash_fname = get_stash_fname(svn, stash_idx)
rc = Popen([svn, 'patch', stash_fname]).wait()
if rc == 0:
os.unlink(stash_fname)
out.write('Popped stash %d\n' % stash_idx)
else:
out.write('Error popping stash %d\n' % stash_idx)
else:
out.write('No stashes to pop\n')
else:
out.write('Unknown action "%s"\n' % action)
return RET_OK
def root(argv, svn, out):
out.write(getSVNRoot(svn) + '\n')
return RET_OK
@ -797,6 +878,7 @@ def main(argv):
'binaries': binaries,
'lockable': lockable,
'status': status,
'stash': stash,
}
do_normal_exec = True