From f94756e6150cab74fbd6879e8fa288ddcf6c2f81 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 29 Jul 2013 14:34:11 -0400 Subject: [PATCH] add "clean" subcommand handler --- README | 10 ++++++++++ jsvn | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/README b/README index c0f029d..f59104d 100644 --- a/README +++ b/README @@ -35,6 +35,16 @@ Implemented subcommands: or a tag or branch name) - if is not given the HEAD of the current working-copy URL is used. - also switch to the new branch if -s is given + clean [-x] {-n|-f} [path...] + - remove (or list) unversioned items + options: + -x, --ignore-ignores + - remove/list unversioned items that are ignored by Subversion + -n, --dry-run + - perform a dry-run, i.e. list files that would be removed but do not + actually remove them + -f, --force + - perform the actual removal of unversioned files diff - allow specifying ref1..ref2 syntax to show the diff between two references - references can be tag names, branch names, or 'trunk' diff --git a/jsvn b/jsvn index 7257db1..26d9482 100755 --- a/jsvn +++ b/jsvn @@ -17,6 +17,7 @@ import getopt import signal import platform import tempfile +import shutil STATUS_LINE_REGEX = r'[ACDIMRX?!~ ][CM ][L ][+ ][SX ][KOTB ]..(.+)' @@ -1631,6 +1632,47 @@ def url_h(argv, svn, out, config): out.write(get_svn_url(svn, path) + '\n') return RET_OK +def clean_h(argv, svn, out, config): + argv = argv[1:] # strip command + opts, args = getopt.getopt(argv, 'fnx', + ['force', 'dry-run', 'ignore-ignores']) + force = False + dry_run = False + ignore_ignores = False + for opt, arg in opts: + if opt in ('-f', '--force'): + force = True + elif opt in ('-n', '--dry-run'): + dry_run = True + elif opt in ('-x', '--ignore-ignores'): + ignore_ignores = True + if not force and not dry_run: + sys.stderr.write('Error: specify either -n or -f\n') + return RET_ERR + if force and dry_run: + sys.stderr.write('Error: specify only one of -n or -f\n') + return RET_ERR + status_args = args + if ignore_ignores: + status_args.append('--no-ignore') + clean_paths = [] + pout = Popen([svn, 'status'] + status_args, stdout=PIPE).stdout + for line in iter(pout.readline, ''): + m = re.match(STATUS_LINE_REGEX, line) + if m is not None: + action = line[0] + if action in ('?', 'I'): + clean_paths.append(m.group(1)) + for cp in clean_paths: + if dry_run: + out.write("Would remove %s\n" % cp) + if force: + if os.path.isdir(cp): + shutil.rmtree(cp) + elif os.path.isfile(cp): + os.unlink(cp) + return RET_OK + ########################################################################### # Main # ########################################################################### @@ -1727,6 +1769,7 @@ def do_cmd(argv, realsvn, config, expand=True): 'add': add_h, 'bisect': bisect_h, 'branch': branch_h, + 'clean': clean_h, 'externals': externals_h, 'switch': switch_h, 'merge': merge_h,