=== modified file 'NEWS' --- NEWS +++ NEWS @@ -1,4 +1,11 @@ UNRELEASED CHANGES + + CHANGES: + + * 'bzr mv', 'move', 'rename' unified into a single command with the + same behavior as Unix mv: if the last parameter is a directory, + the sources are moved into it; otherwise the single source is + renamed. (Paul Sladen) IMPROVEMENTS: === modified file 'bzrlib/builtins.py' --- bzrlib/builtins.py +++ bzrlib/builtins.py @@ -276,73 +276,51 @@ print path -class cmd_move(Command): - """Move files to a different directory. - - examples: - bzr move *.txt doc - - The destination must be a versioned directory in the same branch. - """ - takes_args = ['source$', 'dest'] - def run(self, source_list, dest): - b, source_list = branch_files(source_list) - - # TODO: glob expansion on windows? - tree = WorkingTree(b.base, b) - b.move(source_list, tree.relpath(dest)) - - class cmd_rename(Command): - """Change the name of an entry. - - examples: - bzr rename frob.c frobber.c - bzr rename src/frob.c lib/frob.c - - It is an error if the destination name exists. - - See also the 'move' command, which moves files into a different - directory without changing their name. - """ - # TODO: Some way to rename multiple files without invoking - # bzr for each one?""" - takes_args = ['from_name', 'to_name'] - - def run(self, from_name, to_name): - b, (from_name, to_name) = branch_files((from_name, to_name)) - b.rename_one(from_name, to_name) - - -class cmd_mv(Command): """Move or rename a file. usage: - bzr mv OLDNAME NEWNAME - bzr mv SOURCE... DESTINATION + bzr rename oldname.c newname.c + bzr rename src/frob.c lib/tickle.cpp + bzr rename fred.c fred.h directory/ + bzr rename *.c *.h *.exe ../new/location/ If the last argument is a versioned directory, all the other names are moved into it. Otherwise, there must be exactly two arguments and the file is changed to a new name, which must not already exist. + The destination must be a versioned directory in the same branch; Files cannot be moved between branches. """ - takes_args = ['names*'] - def run(self, names_list): - if len(names_list) < 2: - raise BzrCommandError("missing file argument") - b, rel_names = branch_files(names_list) + # NOTES: 'rename', 'move' and 'mv' were all combined into a single + # command called 'rename' with the symantics of Unix 'mv'. + # 'move' and 'mv' have been brought over as aliases. + + # TODO: This takes_args gives the help text "bzr: ERROR: command + # 'rename' needs one or more SOURCES" when it should give + # "bzr: ERROR: command 'rename' requires a DESTINATION" + # FIXED in commands.py so that 'foo$' does the Right Thing(tm) + + takes_args = ['sources$', 'destination'] + aliases = ['move', 'mv'] + + def run(self, sources_list, destination): + # TODO: glob expansion on windows? + # Error checking is now handled in command.py/_match_argform with '$' arguments + b, rel_names = branch_files(sources_list) - if os.path.isdir(names_list[-1]): - # move into existing directory - for pair in b.move(rel_names[:-1], rel_names[-1]): + if os.path.isdir(destination): + # move into existing versioned directory + tree = WorkingTree(b.base, b) + for pair in b.move(rel_names[:], tree.relpath(destination)): print "%s => %s" % pair else: - if len(names_list) != 2: - raise BzrCommandError('to mv multiple files the destination ' + if len(sources_list) != 1: + raise BzrCommandError('to move multiple files into a new location, the destination ' 'must be a versioned directory') - b.rename_one(rel_names[0], rel_names[1]) - print "%s => %s" % (rel_names[0], rel_names[1]) + b.rename_one(rel_names[0], destination) + print "%s => %s" % (rel_names[0], destination) + class cmd_pull(Command): === modified file 'bzrlib/commands.py' --- bzrlib/commands.py +++ bzrlib/commands.py @@ -374,7 +374,7 @@ # step through args and takes_args, allowing appropriate 0-many matches for ap in takes_args: argname = ap[:-1] - if ap[-1] == '?': + if ap[-1] == '?': # zero or one (optional) if args: argdict[argname] = args.pop(0) elif ap[-1] == '*': # all remaining arguments @@ -383,21 +383,31 @@ args = [] else: argdict[argname + '_list'] = None - elif ap[-1] == '+': + elif ap[-1] == '+': # one or more, all remaining arguments if not args: raise BzrCommandError("command %r needs one or more %s" % (cmd, argname.upper())) else: argdict[argname + '_list'] = args[:] args = [] - elif ap[-1] == '$': # all but one - if len(args) < 2: + elif ap[-1] == '$': # one or more, all but the last one + # Passed in: Error required: + # 0: NEEDS ONE OR MORE _THIS_ + # 1: this NEEDS _THAT_ (achieve by fall-through) + # 2: this that FINE + # 3: this this that FINE + + if len(args) < 1: raise BzrCommandError("command %r needs one or more %s" % (cmd, argname.upper())) - argdict[argname + '_list'] = args[:-1] - args[:-1] = [] - else: - # just a plain arg + if len(args) == 1: + # Falls through so that the last argument errors + argdict[argname + '_list'] = args[:] + args[:] = [] + else: + argdict[argname + '_list'] = args[:-1] + args[:-1] = [] + else: # just a plain arg argname = ap if not args: raise BzrCommandError("command %r requires argument %s" === modified file 'bzrlib/help.py' --- bzrlib/help.py +++ bzrlib/help.py @@ -36,7 +36,7 @@ bzr add make files or directories versioned bzr ignore ignore a file or pattern - bzr mv move or rename a versioned file + bzr rename move or rename a versioned file bzr status summarize changes in working copy bzr diff show detailed diffs === modified file 'contrib/zsh/_bzr' --- contrib/zsh/_bzr +++ contrib/zsh/_bzr @@ -81,7 +81,7 @@ fi ;; - (rename|mv) + (rename|move|mv) if (( CURRENT == 2 )); then _arguments $helpArgs '*:old name:_versionedFiles' else @@ -263,14 +263,6 @@ '--versioned[Print versioned files]' ;; - (move) - if (( CURRENT == 2 )); then - _arguments $helpArgs '*:files:_versionedFiles' - else - _arguments '*:destination dir:_files -/' - fi - ;; - (help) _bzr_subcommands=(${(f)"$(_call_program bzr bzr shell-complete)"}) _arguments $helpArgs \