monotone-commits-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Monotone-commits-diffs] net.venge.monotone.list_workspaces: 3eec39d95c


From: code
Subject: [Monotone-commits-diffs] net.venge.monotone.list_workspaces: 3eec39d95c85a2683b9b1f4245923712b5b9ec22
Date: Tue, 11 Jan 2011 23:20:26 GMT

revision:            3eec39d95c85a2683b9b1f4245923712b5b9ec22
date:                2011-01-11T23:03:05
author:              address@hidden
branch:              net.venge.monotone.list_workspaces
changelog:
propagate from branch 'net.venge.monotone' (head 
cf9d36de0722b365dde0b99578325d490e16d3ba)
            to branch 'net.venge.monotone.list_workspaces' (head 
b5eabe26d8db8d24a28251912e7a6e38a01a1f64)

manifest:
format_version "1"

new_manifest [e7fefa7c86ef54f46fcf2495f692c44400374e23]

old_revision [b5eabe26d8db8d24a28251912e7a6e38a01a1f64]

patch "NEWS"
 from [158aeaaa4f6dc2adee1de8f698bcf52783cf9633]
   to [f9ce17392993af31e59748c969baa33ab5296c42]

patch "cmd_list.cc"
 from [4699a0a7032e69959f8836195977a67888f30848]
   to [f706db0c8374b743160e1ac88cbd863f67f0b2b3]

patch "diff_output.cc"
 from [aeb8a9d42f608944af177b292651de8ba27ca7b4]
   to [1e537406208bd9ff6afd2a728389d1c4f34acaf2]

patch "merge_content.cc"
 from [7b3d119b5dbc73304ab5b11fba31fc78c10b82d8]
   to [620a2b95ee5b72299ee2780ec0077e25c03b8795]

patch "monotone.texi"
 from [ce267276169e98b0d488c741a14ae39a7da69466]
   to [158f3a46762c3b3a5f7d6eecabcd843520706e74]

patch "simplestring_xform.cc"
 from [de3c230648303fb799bdd907bb90985d2ed7e97a]
   to [e779da92dc0c8e2f09d5800d26073d4d2ca5d130]

patch "simplestring_xform.hh"
 from [fb077a97ed6338787a652441b97c809750aac454]
   to [ab0d125445f13982344bbe3f713e2ce90d11cb66]

patch "tests/automate_file_merge/__driver__.lua"
 from [b3f8fc5291e23981a76c9c30352978ae1127d488]
   to [15a2032d1312df8460a20bcbcfb54d995a02ad49]

patch "tests/resolve_conflicts_content/__driver__.lua"
 from [00570ab4eeccfc248746cca7ffada958461d4102]
   to [1b10a05d8783432462a1af35c855035d59383361]

patch "tests/resolve_conflicts_content/merge-1"
 from [bb23ecbb7f05a2de91d69a101ef6df827173c202]
   to [0a6aa4e9b65e60ab29cdd4c6467e9c4e7cc51dd4]

patch "tests/resolve_conflicts_content/update-1"
 from [2db72e362d04f0510378fc7b364d9cc6d1bc7e9f]
   to [d46c485d67feccba79540fc6cd164d963ffdf500]

patch "tests/workspace_migration/twoparent-2/testfile"
 from [a9c24589987aa6b2771ec6d8a419499a563bfa31]
   to [ee18013e989404cbf57ff0af6db2a6c7ed17299d]

old_revision [cf9d36de0722b365dde0b99578325d490e16d3ba]

add_dir "tests/list_workspaces"

add_file "tests/list_workspaces/__driver__.lua"
 content [d7cc622b5a893fd344653512a434440082dbc247]

patch "cmd_list.cc"
 from [1c449f70b7633a20c1caf2f284494b9959ff0ca9]
   to [f706db0c8374b743160e1ac88cbd863f67f0b2b3]

patch "database.cc"
 from [c4d5eb755d893255d1be35276e2b12ccbea8372c]
   to [9b6b20b6b342f4294e9e9d6cfd42d228db7ad18f]

patch "lua_hooks.cc"
 from [a71ded3aabcde9e0ef7281b7c56f2ff1fa6baaec]
   to [a4d6c802bf0190bb5e2223219ea29b2830c7f424]

patch "lua_hooks.hh"
 from [66b79c7d1dcefed2d3530e71474346b72417fee9]
   to [325fd5a4b588ff4d41e3cec69cbf652089a33fa9]

patch "monotone.texi"
 from [f5888ea220ab4b3eae171fb987c5b50eb6b532e4]
   to [158f3a46762c3b3a5f7d6eecabcd843520706e74]

patch "std_hooks.lua"
 from [b1a61ba83a6e8c0c9d72393aaf0e86089b75464d]
   to [78fd8d92d19d3369b8af5809d4bda43f859e8e5e]

patch "tests/list_databases/__driver__.lua"
 from [c63bada5754b3e950bdfb29afdd2cb057c5290b2]
   to [d78cd923f7f4950590407127854dcd3467b85625]

patch "work.cc"
 from [304b3f0ad0624464b9b16b23d0dcb78b4a8effb2]
   to [3c717e59b3acf99ee9cdb49ff688cad9e11472f3]
============================================================
--- NEWS	158aeaaa4f6dc2adee1de8f698bcf52783cf9633
+++ NEWS	f9ce17392993af31e59748c969baa33ab5296c42
@@ -29,6 +29,9 @@ XXX XXX XX XX:XX:XX UTC 2010
         
         Bugs fixed
 
+        - The internal line merger will actually preserve your line
+          endings now, instead of changing everything to "\n".
+
         - Improve help, fix arg indexing in 'conflicts resolve_first'
           (fixes monotone issue 101)
         
============================================================
--- diff_output.cc	aeb8a9d42f608944af177b292651de8ba27ca7b4
+++ diff_output.cc	1e537406208bd9ff6afd2a728389d1c4f34acaf2
@@ -485,8 +485,8 @@ make_diff(string const & filename1,
     }
 
   vector<string> lines1, lines2;
-  split_into_lines(data1(), lines1, true);
-  split_into_lines(data2(), lines2, true);
+  split_into_lines(data1(), lines1, split_flags::diff_compat);
+  split_into_lines(data2(), lines2, split_flags::diff_compat);
 
   vector<long, QA(long)> left_interned;
   vector<long, QA(long)> right_interned;
============================================================
--- monotone.texi	ce267276169e98b0d488c741a14ae39a7da69466
+++ monotone.texi	158f3a46762c3b3a5f7d6eecabcd843520706e74
@@ -3209,25 +3209,25 @@ @section Merge Conflicts
 In addition, the @command{conflicts} set of commands can be used to
 specify resolutions for some conflicts. The resolutions are stored in a
 file, and given to the @command{merge} command via the
address@hidden or
address@hidden option; see @ref{Conflicts}.
address@hidden or
address@hidden option; see @ref{Conflicts}.
 
 The @command{merge} command normally will perform as many merges as
 necessary to merge all current heads of a branch. However, when
address@hidden is given, the conflicts and their
address@hidden is given, the conflicts and their
 resolutions apply only to the first merge, so the subsequent merges
 are not done; the @command{merge} command must be repeated, possibly
 with new conflicts and resolutions, to merge the remaining heads.
 
 For the special case of file content conflicts, a merge command
-invoked without @command{--resolve-conflicts} will attempt to start an
+invoked without @option{--resolve-conflicts} will attempt to start an
 external interactive merge tool; the user must then resolve the conflicts
 and terminate the merge tool, letting monotone continue with the
 merge. This process is repeated for each file content conflict. See
 @ref{File Content Conflict} below for more detail.
 
 For other conflicts, a merge command invoked without
address@hidden will fail.
address@hidden will fail.
 
 If @command{conflicts} supports resolving a particular conflict, that
 is the simplest way to resolve it. Otherwise, resolving the different
@@ -3271,7 +3271,7 @@ @subheading File Content Conflict
 
 If @code{mtn:manual_merge} is present and @code{true}, or if the
 changes are to the same lines of the file, and neither
address@hidden nor @command{--non-interactive} was
address@hidden nor @option{--non-interactive} was
 specified, the @ref{merge3} hook is called, with the content of both
 conflicting versions and their common ancestor.
 
@@ -3281,7 +3281,7 @@ @subheading File Content Conflict
 @smallexample
 mtn conflicts resolve_first user filename
 @end smallexample
-Then @command{--resolve-conflicts} is specified on the merge command
+Then @option{--resolve-conflicts} is specified on the merge command
 line.
 
 Finally, rather than using a merge tool it is possible to commit
@@ -3786,7 +3786,7 @@ @section Managed Databases
 
 @node Managed Databases, Reserved Files, Vars, Advanced Uses
 @section Managed Databases
-In monotone commands, a database name (provided to a @command{--db}
+In monotone commands, a database name (provided to a @option{--db}
 option) starting with ``:'' is a ``database alias''. The rest of the
 database name is a file name; the file extension @file{.mtn} is added
 if the file name has no extension. The file is searched for in the
@@ -4886,7 +4886,7 @@ @chapter Command Reference
 help for those.
 
 @menu
-* Global Options::              Options that affect all commands
+* Global and Common Options::   Options that affect all or many commands
 * Tree::                        Operations on tree states in your database
 * Workspace::                   Operations on your workspace
 * Network::                     Communication with the network
@@ -4904,15 +4904,25 @@ @chapter Command Reference
 @c this manual.
 
 @page
address@hidden    Global Options, Tree, Command Reference, Command Reference
address@hidden Global Options
address@hidden    Global and Common Options, Tree, Command Reference, Command Reference
address@hidden Global and Common Options
+
address@hidden
+* Global Options::
+* Common Options::
address@hidden menu
+
address@hidden Global Options
address@hidden Global Options
+These options are available on all commands.
+
 @ftable @command
 @item --confdir <arg>
 Set the location of the configuration directory (default
 @file{$HOME/.monotone} on Unix and Cygwin, @file{%APPDATA%\monotone%} on
 Windows MinGW). In this manual, references to these specific directories are
 actually references to the directory specified by
address@hidden
address@hidden
 
 The configuration directory is where monotone finds:
 
@@ -4920,7 +4930,7 @@ @section Global Options
 @item keys
 in @file{confdir/keys}; see @ref{Certificates}, @ref{Generating
 Keys}. The location of the keys directory can be overridden separately
-with the @command{--keydir} option.
+with the @option{--keydir} option.
 
 @item monotonerc
 which is a per-user configuration file containing Lua code
@@ -4968,11 +4978,13 @@ @section Global Options
 Do not ignore revisions marked as suspended; see the @command{mtn
 suspend} command.
 
address@hidden --key <arg>
address@hidden@item --key <arg>
 @itemx --use-default-key
 Set the key for signatures, using either the key name or the key hash
-(see @ref{Generating Keys}).  If there is only one key in the keydir, then
-that is the default key. Otherwise there is no default key.
+(see @ref{Generating Keys}).  If there is only one key in the keydir,
+then that is the default key. Otherwise there is no default key. If no
+key is specified (by this option or by default), and the command needs
+a key, then the user is prompted for the key to use.
 
 @item --keydir <arg>
 Set the key directory (where the ``key store'' is located); default is
@@ -4991,14 +5003,13 @@ @section Global Options
 
 @item --no-default-confdir
 @itemx --allow-default-confdir
-Don't use a default confdir; @command{--confdir} must be specified if
+Don't use a default confdir; @option{--confdir} must be specified if
 a configuration file is needed.
 
 @item --no-format-dates
 Print date certs exactly as stored in the database.
 
address@hidden --no-standard-rcfiles
address@hidden --standard-rcfiles
address@hidden --[no-]standard-rcfiles
 Do not load the standard rcfiles, which are
 @file{$HOME/.monotone/monotonerc} on Unix or
 @file{%APPDATA%\monotone\monotonerc} on Windows, and
@@ -5023,8 +5034,8 @@ @section Global Options
 @item --rcfile <arg>
 Specify an extra rcfile to load. See @ref{rcfiles}.
 
address@hidden --clear-rcfiles
-Cancel all previous @command{--rcfile} options (standard rcfiles are
address@hidden --clear-rcfiles
+Cancel all previous @option{--rcfile} options (standard rcfiles are
 still loaded). See @ref{rcfiles}.
 
 @itemx --root <arg>
@@ -5050,7 +5061,39 @@ @section Global Options
 Insert command line arguments taken from the given file.
 @end ftable
 
address@hidden    Tree, Workspace, Global Options, Command Reference
address@hidden Common Options
address@hidden Common Options
+These options are available on many commands.
address@hidden @command
address@hidden@item --author
+Override the author cert for a commit; normally, the author is the
+name of the key used for the commit. See @ref{--key}.
+
address@hidden@item --branch
+Specify the branch for a command. This normally defaults to the
+workspace branch.
+
address@hidden@item --date
+Override the date cert for a commit. The date defaults to the current
+calendar time.
+
address@hidden@item --message @var{string}
+Set the commit changelog message, as a string. Each command that does
+a commit has a different default for the message.
+
address@hidden@item --message-file @var{filename}
+Set the commit changelog message, as a file. Each command that does
+a commit has a different default for the message.
+
address@hidden@item --[no-]update
+If @option{--update} is given, and the command is executed in a
+workspace, the workspace is updated to the new head of the workspace
+branch if the workspace was at a head, and the command makes a new
+head of the workspace branch.
+
address@hidden ftable
+
address@hidden    Tree, Workspace, Global and Common Options, Command Reference
 @section Tree
 
 @ftable @command
@@ -5105,8 +5148,8 @@ @section Tree
 @item mtn conflicts
 See @ref{Conflicts}
 
address@hidden mtn explicit_merge @var{id} @var{id} @var{destbranch}
-See the online help for options.
address@hidden mtn explicit_merge [--[no-]update] @var{id} @var{id} @var{destbranch}
+See the online help for options. See @ref{--update}.
 
 This command merges exactly the two @var{id}s you give it, and places
 the result in branch @var{destbranch}.  It is useful when you need more
@@ -5141,7 +5184,7 @@ @section Tree
 branch already exists, any missing files are dropped and any unknown
 files are added before committing.
 
-If @command{--dry-run} is given, no commit is done.
+If @option{--dry-run} is given, no commit is done.
 
 Roughly speaking, @command{mtn import} does the following:
 
@@ -5158,8 +5201,8 @@ @section Tree
 to be the given revision or the head of the given branch instead of the
 null revision.
 
address@hidden mtn merge address@hidden [--message @var{string}] [--message-file @var{filename}]
-See the online help for more options.
address@hidden mtn merge address@hidden [--message @var{string}] [--message-file @var{filename}] [--[no-]update]
+See the online help for more options. See @ref{--update}.
 
 This command merges the ``heads'' of @var{branchname} (default the
 branch of the current workspace), if there are multiple heads, and
@@ -5167,8 +5210,8 @@ @section Tree
 revision as a member of @var{branchname}. The merged revision will
 contain each of the head revision IDs as ancestors.
 
-A commit message may be provided via @command{--message @var{string}}
-or @command{--message-file @var{filename}}. A message stating the
+A commit message may be provided via @option{--message @var{string}}
+or @option{--message-file @var{filename}}. A message stating the
 revision ids that were merged will be prepended to any user commit
 message.
 
@@ -5180,7 +5223,7 @@ @section Tree
 
 @ref{Merge Conflicts} can occur.
 
address@hidden mtn merge_into_dir @var{sourcebranch} @var{destbranch} @var{dir}
address@hidden mtn merge_into_dir [--[no-]update] @var{sourcebranch} @var{destbranch} @var{dir}
 This command takes a unique head from @var{sourcebranch} and merges it
 into a unique head of @var{destbranch}, as a directory. The resulting
 revision is committed to @var{destbranch}. If either @var{sourcebranch} or
@@ -5199,7 +5242,7 @@ @section Tree
 originally in @var{sourcebranch}, which is almost certainly not what would be
 intended.
 
address@hidden Conflicts} can occur.
address@hidden Conflicts} can occur. See @ref{--update}.
 
 @item mtn merge_into_workspace [--[no]-move-conflicting-paths] @var{revision}
 Merges @var{revision} into the current workspace; the result is not
@@ -5229,8 +5272,8 @@ @section Tree
 either @var{sourcebranch} or @var{destbranch} has multiple heads,
 @command{propagate} aborts, doing nothing.
 
-A commit message may be provided via @command{--message @var{string}}
-or @command{--message-file @var{filename}}. A message stating the
+A commit message may be provided via @option{--message @var{string}}
+or @option{--message-file @var{filename}}. A message stating the
 source and target branches will be prepended to any user commit
 message.
 
@@ -5283,9 +5326,9 @@ @subsection Conflicts
 These commands require a workspace, to provide a place to store the
 conflicts and user resolution files.
 
-For all of these commands, if the @command{--conflicts-file} option is
+For all of these commands, if the @option{--conflicts-file} option is
 not given, the file @file{_MTN/conflicts} is used. If the
address@hidden option is given, the file must be in the
address@hidden option is given, the file must be in the
 bookkeeping directory.
 
 Files given in these commands are relative to the current working
@@ -5426,7 +5469,7 @@ @section Workspace
 next @command{commit}. See @ref{Storage and workflow} for
 more information on @command{add} and @command{commit}.
 
-As a convenience, the @command{--unknown @var{pathname...}} option can be used;
+As a convenience, the @option{--unknown @var{pathname...}} option can be used;
 this option will cause all of the files listed by @command{mtn list
 unknown @var{pathname...}} to be added.
 
@@ -5713,7 +5756,7 @@ @section Workspace
 
 This command places @code{rename} entries for the paths specified in
 @var{src} and @var{dst} in @ref{_MTN/revision}, and (if
address@hidden is not specified) renames the paths on the
address@hidden is not specified) renames the paths on the
 disk. This will be part of the next @command{commit}.
 
 The second form renames a number of source paths (or a single source,
@@ -5741,7 +5784,7 @@ @section Workspace
 @item mtn undrop @var{pathname...}
 Undoes a previous @command{drop}; useful when you make a mistake. If
 the file was deleted from the workspace, this reverts it. If it was
-not deleted (because it was changed or @command{--bookkeep-only} was
+not deleted (because it was changed or @option{--bookkeep-only} was
 given), it just removes the pending drop.
 
 @anchor{mtn address@hidden mtn update [--[no-]move-conflicting-paths] [--branch @var{branchname}]
@@ -5751,11 +5794,11 @@ @section Workspace
 
 @command{update} performs 3 separate stages. If any of these stages
 fails, the update aborts, doing nothing. The first two stages select
-the target revision; they are skipped if @command{--revision} is given
+the target revision; they are skipped if @option{--revision} is given
 - that revision is the target.
 
-In the first stage, if @command{--branch} is not given, the workspace
-branch is used. If @command{--branch} is given, the branch becomes the
+In the first stage, if @option{--branch} is not given, the workspace
+branch is used. If @option{--branch} is given, the branch becomes the
 new default branch of the workspace (even if you also specify an
 explicit @option{--revision} argument).
 
@@ -5801,7 +5844,7 @@ @section Network
 @itemx mtn pull [--[no-]set-default] address@hidden address@hidden [...] address@hidden @strong{deprecated}
 @itemx mtn push [--[no-]set-default] address@hidden address@hidden address@hidden [...] address@hidden @strong{deprecated}
 @itemx mtn sync [--[no-]set-default] address@hidden address@hidden address@hidden [...] address@hidden @strong{deprecated}
-See the online help for more options.
+See the online help for more options. See @ref{--update}.
 
 These commands operate the ``netsync'' protocol built into
 monotone. This is a custom protocol for rapidly synchronizing two
@@ -5960,7 +6003,7 @@ @section Network
 Finally, @command{clone} copies the files out of the newly created
 database into a local directory, just as @command{checkout} would.  If
 no @var{directory} is given, the @var{branchname} is used as
-directory. If @command{--revision} is given, that revision must be on
+directory. If @option{--revision} is given, that revision must be on
 the specified branch, and is checked out; otherwise the head of the
 branch is checked out.
 
@@ -5976,35 +6019,45 @@ @section Informative
 @item mtn annotate @var{file}
 @itemx mtn annotate address@hidden [--revs-only] @var{file}
 
-Dumps an annotated copy of the file to stdout. The output is in the form
-<short revision id>.. by <author> <date>: <line> Only the first 8
-characters of the revision id are displayed, the author cert value is
-truncated at the first @code{@@} or space character and the date field
-is truncated to remove the time of day.
+Dumps an annotated copy of the file to stdout. The output is in the
+form:
 
-If @option{--revs-only} is specified, each line of the file is
-translated to <revision id>: <line> in the output, where <revision id>
-is the revision in which that line of the file was last edited.
address@hidden
+<short revision id>.. by <author> <date>: <line>
address@hidden example
 
address@hidden mtn bisect good address@hidden ...] [--[no-]move-conflicting-paths]
-Mark the specified revisions as ``good'' for the current bisection
-operation. If no bisection operation is in progress a new bisection is
-initialized. If a bisection operation is in progress the next update
-target is selected and the workspace is updated to the selected
-revision.
+<revision id> is the revision in which that line of the file was last
+edited; <author> is the author cert on that revision, <date> is the
+date cert on that revision.
 
+Only the first 8 characters of the revision id are displayed, the
+author cert value is truncated at the first @code{@@} or space
+character and the date field is truncated to remove the time of day.
+
+If @option{--revs-only} is specified, the output format is:
address@hidden
+ <revision id>: <line>
address@hidden example
+
address@hidden mtn bisect bad address@hidden ...] [--[no-]move-conflicting-paths]
+Mark the specified revisions as ``bad'' for the current bisection
+operation (see @ref{Bisecting}). If no bisection operation is in
+progress a new bisection is initialized. If a bisection operation is
+in progress the next update target is selected and the workspace is
+updated to the selected revision.
+
 If the update is blocked by conflicting unversioned paths existing in
 the workspace this command may be re-issued with the
 @option{--move-conflicting-paths} option. Alternatively, the
 @command{bisect update} command can be used with this option to update
 the workspace and move the conflicting paths out of the way.
 
address@hidden mtn bisect bad address@hidden ...] [--[no-]move-conflicting-paths]
-Mark the specified revisions as ``bad'' for the current bisection
-operation. If no bisection operation is in progress a new bisection is
-initialized. If a bisection operation is in progress the next update
-target is selected and the workspace is updated to the selected
-revision.
address@hidden mtn bisect good address@hidden ...] [--[no-]move-conflicting-paths]
+Mark the specified revisions as ``good'' for the current bisection
+operation (see @ref{Bisecting}). If no bisection operation is in
+progress a new bisection is initialized. If a bisection operation is
+in progress the next update target is selected and the workspace is
+updated to the selected revision.
 
 If the update is blocked by conflicting unversioned paths existing in
 the workspace this command may be re-issued with the
@@ -6012,12 +6065,17 @@ @section Informative
 @command{bisect update} command can be used with this option to update
 the workspace and move the conflicting paths out of the way.
 
address@hidden mtn bisect reset
+Reset the current bisection operation by updating the workspace back
+to the revision from which the bisection was started and clearing the
+current bisection information.
+
 @item mtn bisect skip address@hidden ...] [--[no-]move-conflicting-paths]
 Mark the specified revisions as ``skipped'' for the current bisection
-operation. If no bisection operation is in progress a new bisection is
-initialized. If a bisection operation is in progress the next update
-target is selected and the workspace is updated to the selected
-revision.
+operation (see @ref{Bisecting}). If no bisection operation is in
+progress a new bisection is initialized. If a bisection operation is
+in progress the next update target is selected and the workspace is
+updated to the selected revision.
 
 If the update is blocked by conflicting unversioned paths existing in
 the workspace this command may be re-issued with the
@@ -6025,38 +6083,25 @@ @section Informative
 @command{bisect update} command can be used with this option to update
 the workspace and move the conflicting paths out of the way.
 
address@hidden mtn bisect update [--[no-]move-conflicting-paths]
-Update the workspace to the next revision selected by the previous
-bisect operation. This command can be useful when the previous bisect
-operation fails to update the workspace because of conflicting
-unversioned paths existing in the workspace.
-
 @item mtn bisect status
 Report the status of the current bisection operation including the
 number of revisions that remain to be tested, the number of revisions
 that have been tested and the next revision that will selected for
 testing.
 
address@hidden mtn bisect reset
-Reset the current bisection operation by updating the workspace back
-to the revision from which the bisection was started and clearing the
-current bisection information.
address@hidden mtn bisect update [--[no-]move-conflicting-paths]
+Update the workspace to the next revision selected by the previous
+bisect operation (see @ref{Bisecting}). This command can be useful
+when the previous bisect operation fails to update the workspace
+because of conflicting unversioned paths existing in the workspace.
 
address@hidden mtn cat @var{path}
address@hidden mtn cat address@hidden @var{path}
address@hidden mtn cat address@hidden @var{path}
+Write the contents of a specific file @var{path} in revision @var{id}
+(default to workspace base revision) to standard output.
 
-Write the contents of a specific file @var{path} to standard output.
-
-Without a @option{--revision} argument, the command outputs the
-contents of @var{path} as found in the current revision. This requires
-the command be executed from within a workspace.
-
-With an explicit @option{--revision} argument, the command outputs
-contents of @var{path} at that revision.
-
 @item mtn complete file @var{partial-id}
address@hidden mtn complete [--brief] key @var{partial-id}
address@hidden mtn complete [--brief] revision @var{partial-id}
address@hidden mtn complete key @var{partial-id}
address@hidden mtn complete revision @var{partial-id}
 
 These commands print out all known completions of a partial @sc{sha1}
 value, listing completions which are @code{file}, @code{manifest} or
@@ -6077,20 +6122,6 @@ @section Informative
 @code{fa36}. This command is intended to be used by programmable
 completion systems, such as those in @command{bash} and @command{zsh}.
 
-The complete command for keys and revisions have a @option{--verbose} option.
-Programmable completion systems can use @option{--verbose} output to
-present users with additional information about each completion option.
-
-For example, verbose output for @code{revision} looks like this:
address@hidden
address@hidden
-$ mtn complete revision 01f
-01f5da490941bee1f0000f0561fc62eabfb2fa23 graydon@@dub.net 2003-12-03T03:14:35
-01f992577bd8bcdcade0f89e724fd5dc2d2bbe8a kinetik@@orcon.nz 2005-05-11T05:19:29
-01faad191d8d0474777c70b4d606782942333a78 kinetik@@orcon.nz 2005-04-11T04:24:01
address@hidden group
address@hidden smallexample
-
 @item mtn diff [--unified] [--[no-]show-encloser]
 @itemx mtn diff --context [--[no-]show-encloser]
 @itemx mtn diff --external address@hidden
@@ -6100,12 +6131,12 @@ @section Informative
 @itemx mtn diff address@hidden address@hidden
 @itemx mtn diff address@hidden address@hidden @var{pathname...}
 @itemx mtn di
address@hidden is an alias for @command{diff}.
address@hidden is an alias for @command{diff}. See online help for more options.
 
-These commands print out GNU ``unified diff format'' textual difference
-listings between various manifest versions. With no @option{--revision}
-options, @command{diff} will print the difference from the
-base revision to the current revision in the workspace.
+These commands print out textual difference listings between various
+manifest versions. With no @option{--revision} options, @command{diff}
+will print the difference from the base revision to the current
+revision in the workspace.
 
 With one @option{--revision} option, @command{diff} will print the
 difference from the revision @var{id} to the current revision in the
@@ -6155,11 +6186,6 @@ @section Informative
 @ref{get_encloser_pattern}.  For the regular _expression_ syntax, see
 @ref{Regexps}.
 
address@hidden requests the ``unified diff'' format, the default.
address@hidden requests the ``context diff'' format (analogous to
-running the program @command{diff @option{-c}}).  Both of these formats are
-generated directly by monotone, using its built-in diff algorithm.
-
 Sometimes, you may want more flexibility in output formats; for these
 cases, you can use @option{--external}, which causes monotone to
 invoke an external program to generate the actual output.  By default,
@@ -6167,9 +6193,9 @@ @section Informative
 @option{--diff-args} to pass additional arguments controlling
 formatting.  The actual invocation of @command{diff}, default
 arguments passed to it, and so on, are controlled by the hook
address@hidden for more details.
address@hidden
 
address@hidden mtn help [--[no]-hidden] @var{command...}
address@hidden mtn help [--[no-]hidden] @var{command...}
 Displays help about commands and options.
 
 @item mtn list branches address@hidden address@hidden
@@ -6182,6 +6208,10 @@ @section Informative
 options are provided they are used as globs to exclude specified
 branches.
 
+Normally, branches that have been suspended are not listed; the global
+option @option{--ignore-suspend-certs} causes suspended branches to
+be listed; see @ref{mtn suspend}.
+
 @item mtn list certs @var{id}
 @itemx mtn ls certs
 @command{ls certs} is an alias for @command{list certs}.
@@ -6191,9 +6221,9 @@ @section Informative
 indicate:
 @itemize
 @item
-Whether the signature on the certificate is @code{ok} or @code{bad}
+The key used to sign the certificate
 @item
-The key used to sign the certificate
+Whether the signature on the certificate is @code{ok} or @code{bad}
 @item
 The name of the certificate
 @item
@@ -6240,10 +6270,10 @@ @section Informative
 @end group
 @end smallexample
 
address@hidden mtn list changed
address@hidden mtn list changed @var{pathname...}
address@hidden mtn list changed address@hidden
 @itemx mtn ls changed
 @command{ls changed} is an alias for @command{list changed}.
+See online help for more options.
 
 This command lists all files in your workspace that have changed
 compared to the base revision, including files that are dropped, added
@@ -6270,21 +6300,20 @@ @section Informative
 @itemx mtn ls duplicates
 @command{ls duplicates} is an alias for @command{list duplicates}.
 
-This command lists duplicate files in a given revision. If no revision is
-given, the workspace is used instead. Ignored and unknown files are
-excluded from the listing.
+This command lists duplicate files in a given revision (defaults to
+the workspace base revision). Ignored and unknown files are excluded
+from the listing.
 
 Two or more files are considered duplicates if the @sc{sha1} hashes of their
 contents are equal.
 
address@hidden mtn list ignored
address@hidden mtn list ignored @var{pathname...}
address@hidden mtn list ignored address@hidden
 @itemx mtn ls ignored
 @command{ls ignored} is an alias for @command{list ignored}.
 
 This command lists all files in your workspace that monotone is
-intentionally ignoring, due to the results of the @code{ignore_file
-(@var{filename})} hook.
+intentionally ignoring, due to the results of the @ref{ignore_file}
+hook.
 
 Specifying pathnames to the @command{list ignored} command restricts the
 set of paths that are searched for ignored files. Ignored files not
@@ -6295,8 +6324,7 @@ @section Informative
 Specifying only the pathname "." will restrict the search for ignored
 files to the current subdirectory of the workspace.
 
address@hidden mtn list keys
address@hidden mtn list keys @var{pattern}
address@hidden mtn list keys address@hidden
 @itemx mtn ls keys
 @command{ls keys} is an alias for @command{list keys}.
 
@@ -6307,8 +6335,7 @@ @section Informative
 If @var{pattern} is provided, it is used as a glob to limit the keys
 listed. Otherwise all keys in your database are listed.
 
address@hidden mtn list known
address@hidden mtn list known @var{pathname...}
address@hidden mtn list known address@hidden
 @itemx mtn ls known
 @command{ls known} is an alias for @command{list known}.
 
@@ -6324,8 +6351,7 @@ @section Informative
 Specifying only the pathname "." will restrict the search for known
 files to the current subdirectory of the workspace.
 
address@hidden mtn list missing
address@hidden mtn list missing @var{pathname...}
address@hidden mtn list missing address@hidden
 @itemx mtn ls missing
 @command{ls missing} is an alias for @command{list missing}.
 
@@ -6345,18 +6371,16 @@ @section Informative
 @itemx mtn ls tags
 @command{ls tags} is an alias for @command{list tags}.
 
-This command lists all known tags in your database. If @var{pattern}
-is provided, it is used as a glob to select the tags listed, otherwise
-all tags are listed.  If @option{-exclude} options are provided they
-are used as globs to exclude specified tags.
+This command lists all known tags in your database that match the
+given @var{pattern} (default all tags).  If @option{--exclude}
+options are provided they are used as globs to exclude specified tags.
 
address@hidden mtn list unknown
address@hidden mtn list unknown @var{pathname...}
address@hidden mtn list unknown address@hidden
 @itemx mtn ls unknown
 @command{ls unknown} is an alias for @command{list unknown}.
 
-This command lists all files in your workspace that monotone is
-either ignoring or knows nothing about.
+This command lists all files in your workspace that monotone knows
+nothing about.
 
 Specifying pathnames to the @command{list unknown} command restricts the
 set of paths that are searched for unknown files. Unknown files not
@@ -6367,8 +6391,7 @@ @section Informative
 Specifying only the pathname "." will restrict the search for unknown
 files to the current subdirectory of the workspace.
 
address@hidden mtn list vars
address@hidden mtn list vars @var{domain}
address@hidden mtn list vars address@hidden
 @itemx mtn ls vars
 @command{ls vars} is an alias for @command{list vars}.
 
@@ -6386,6 +6409,7 @@ @section Informative
 
 @anchor{mtn address@hidden mtn log
 @itemx mtn log address@hidden address@hidden address@hidden [...]] [--clear-from] address@hidden [...]] [--clear-to] address@hidden [...]] [--[no-]brief] [--[no-]merges] [--[no-]files] [--[no-]graph] [--[no-]diffs] address@hidden
+See the online help for more options.
 
 This command prints out a log, in forward ancestry order by default
 but optionally in reverse ancestry order, of small history summaries.
@@ -6463,7 +6487,7 @@ @section Informative
 @item mtn manpage [--formatted/--plain] [--[no-]hidden]
 The manpage command generates a complete (and if monotone is available
 in your language, also localized) manual page for all available commands,
-including all custom Lua commands.
+including all user-defined Lua commands.
 
 If the command's output is directly written to a terminal, its output is
 automatically formatted using @command{nroff} and displayed in the
@@ -6472,7 +6496,7 @@ @section Informative
 option to the command and the @option{--plain} option to achieve the
 opposite, i.e. plain, unformatted troff output.  If you wish to use a
 different formatter or pager, please have a look at the
address@hidden Lua hook.
address@hidden Lua hook.
 
 The option @option{--hidden} additionally enables the output of hidden
 commands and options, which is deactivated by default.
@@ -6484,8 +6508,7 @@ @section Informative
 Note that this does not show conflicts due to update commands, since
 in that case one revision is the workspace.
 
address@hidden mtn status
address@hidden mtn status @var{pathname...}
address@hidden mtn status address@hidden
 This command prints a description of the ``status'' of your workspace.
 In particular, it prints:
 @itemize
@@ -6528,55 +6551,71 @@ @section Review
 @section Review
 
 @ftable @command
address@hidden mtn approve @var{id}
-This command is a synonym for @command{mtn cert @var{id} branch
address@hidden where @var{branchname} is the current branch name
-(either deduced from the workspace or from the @option{--branch}
-option).
address@hidden mtn approve @var{rev} address@hidden [--[no-]update]
+This command puts @var{rev} on the branch @var{branchname} (defaults
+to the workspace branch).
 
address@hidden mtn comment @var{id}
address@hidden mtn comment @var{id} @var{comment}
-These commands are synonyms for @command{mtn cert @var{id}
-comment @var{comment}}. If @var{comment} is not provided, it is read
-from @code{stdin}.
+This command is a synonym for @command{mtn cert @var{rev} branch
address@hidden
 
address@hidden mtn disapprove address@hidden @var{child}
+See @ref{--update}.
+
address@hidden mtn comment @var{rev} address@hidden
+
+This adds a new comment to a committed revision.  If @var{comment} is
+not provided, it is read from @code{stdin}.
+
+This command is a synonym for @command{mtn cert @var{rev} comment
address@hidden
+
address@hidden mtn disapprove [--[no-]update] address@hidden @var{child}
+See online help for more options; see @ref{Common Options}. See @ref{--update}.
+
 This command records a disapproval of the changes between @var{parent}'s
 ancestor and @var{child}.  If @var{parent} is omitted, only @var{child}
 is disapproved.  The command does the disapproval by committing
 the @i{inverse} changes as a new revision descending from @var{child}.
-The new revision will show up as a new head and thus a subsequent
address@hidden will incorporate the inverse of the disapproved changes
-in the other head(s).
 
-Conceptually, @command{disapprove}s contract is that disapprove(A) gives a
+Conceptually, @command{disapprove}'s contract is that disapprove(A) gives a
 revision B such that whenever B is merged with a descendant D of A the merge
 will result in what D ``would have looked like'' if A had never happened.
 
-Note that as a consequence of this contract the @command{disapprove} command
-only works if all changesets from @var{parent} to @var{child} have exactly
-one ancestor, since it hasn't been worked out how to generate such
-a descendant in the multi-ancestor case.
+Note that as a consequence of this contract the @command{disapprove}
+command only works if all changesets from @var{parent} to @var{child}
+have exactly one ancestor (that is, none are the result of a merge),
+since it hasn't been worked out how to generate such a descendant in
+the multi-ancestor case.
 
address@hidden mtn suspend @var{id}
-This command is a synonym for @command{mtn cert @var{id} suspend
address@hidden where @var{branchname} is the current branch name
-(either deduced from the workspace or from the @option{--branch}
-option).
address@hidden address@hidden mtn suspend [--[no-]update] [--branch @var{branchname}] @var{rev}
+See @ref{--update}.
 
address@hidden mtn tag @var{id} @var{tagname}
+This makes @var{rev} invisible as a head of branch @var{branchname}
+(defaults to the current workspace branch).  Any operation that looks
+for heads will not count @var{rev}; this includes @command{mtn list branches}
+as well as @command{mtn merge} etc.
+
+If @var{rev} is not a head, @command{suspend} has no effect.
+
address@hidden is not inherited; if a new revision is committed as
+the child of a @command{suspend}ed revision, the new revision will be
+visible as a head.
+
+This command is a synonym for @command{mtn cert @var{rev} suspend
address@hidden
+
address@hidden mtn tag @var{rev} @var{tagname}
 This command associates the symbolic name @var{tagname} with the
-revision @var{id}, so that symbolic name can later be used in
address@hidden for specifying revisions for commands like
address@hidden or @command{diff}.
+revision @var{rev}, so that symbolic name can later be used in
address@hidden for specifying revisions.
 
-This command is a synonym for @command{mtn cert @var{id} tag
+This command is a synonym for @command{mtn cert @var{rev} tag
 @var{tagname}}.
 
address@hidden mtn testresult @var{id} 0
address@hidden mtn testresult @var{id} 1
-These commands are synonyms for @command{mtn cert @var{id}
-testresult 0} or @command{mtn cert @var{id} testresult 1}.
address@hidden mtn testresult @var{rev} @{pass | fail | true | false | yes | no | 1 | address@hidden
+This command adds a @option{testresult} certificate to @var{rev}, with
+a value of 0 or 1. @option{pass}, @option{true}, @option{yes} give a
+value of 1; @option{fail}, @option{false}, @option{no} give a value of
+0. See @ref{Quality Assurance}.
 
 @end ftable
 
@@ -6946,7 +6985,7 @@ @section Database
 
 Older monotone versions could sometimes associate certs with the wrong
 key. This fixes such certs if you have the correct key, and if
address@hidden is given, drops any certs that you don't
address@hidden is given, drops any certs that you don't
 have the correct key for. This should only be needed if you had such
 certs in your db when upgrading from monotone 0.44 or earlier, or if
 you loaded such certs with 'mtn read'.
@@ -11059,7 +11098,7 @@ @section Automation
 @item Arguments:
 
 Same as @command{mtn update}; no arguments, options
address@hidden, @address@hidden
address@hidden, @address@hidden
 
 @item Added in:
 
@@ -11795,7 +11834,7 @@ @subsection User Defaults
 @end group
 @end smallexample
 
address@hidden ignore_file (@var{filename})
address@hidden@item ignore_file (@var{filename})
 
 Returns @code{true} if @var{filename} should be ignored while adding,
 dropping, or moving files. Otherwise returns @code{false}. This is
@@ -11804,9 +11843,10 @@ @subsection User Defaults
 
 The default definition of this hook recognises a number of common file
 types and extensions for temporary and generated file types that users
-typically don't want to track. If the file @file{.mtn-ignore} exists,
-this hook will read a list of regular expressions from the file, one per
-line, and ignore all files matching one of these expressions. For the
+typically don't want to track. In addition, if the file
address@hidden exists in the root workspace directory, this hook
+will read a list of regular expressions from the file, one per line,
+and ignore all files matching one of these expressions. For the
 default definition of this hook, see @ref{Default hooks}.
 
 @item ignore_branch (@var{branchname})
@@ -11836,7 +11876,7 @@ @subsection User Defaults
 will issue warnings that the format is unsuitable and the
 @command{commit} command will abort.
 
address@hidden get_man_page_formatter_command ()
address@hidden@item get_man_page_formatter_command ()
 
 Specifies the command chain which should be executed if the
 @command{manpage} command is executed interactively. The default is
============================================================
--- merge_content.cc	7b3d119b5dbc73304ab5b11fba31fc78c10b82d8
+++ merge_content.cc	620a2b95ee5b72299ee2780ec0077e25c03b8795
@@ -424,15 +424,18 @@ content_merger::attempt_auto_merge(file_
   string const right_encoding(get_file_encoding(right_path, right_ros));
 
   vector<string> left_lines, ancestor_lines, right_lines, merged_lines;
-  split_into_lines(left_unpacked(), left_encoding, left_lines);
-  split_into_lines(ancestor_unpacked(), anc_encoding, ancestor_lines);
-  split_into_lines(right_unpacked(), right_encoding, right_lines);
+  split_into_lines(left_unpacked(), left_encoding, left_lines,
+                   split_flags::keep_endings);
+  split_into_lines(ancestor_unpacked(), anc_encoding, ancestor_lines,
+                   split_flags::keep_endings);
+  split_into_lines(right_unpacked(), right_encoding, right_lines,
+                   split_flags::keep_endings);
 
   if (merge3(ancestor_lines, left_lines, right_lines, merged_lines))
     {
       string tmp;
 
-      join_lines(merged_lines, tmp);
+      join_lines(merged_lines, tmp, "");
       merge_data = file_data(tmp, origin::internal);
       return true;
     }
============================================================
--- cmd_list.cc	4699a0a7032e69959f8836195977a67888f30848
+++ cmd_list.cc	f706db0c8374b743160e1ac88cbd863f67f0b2b3
@@ -782,7 +782,7 @@ CMD(known, "known", "", CMD_REF(list), "
        ostream_iterator<file_path>(cout, "\n"));
 }
 
-CMD(unknown, "unknown", "ignored", CMD_REF(list), "",
+CMD(unknown, "unknown", "ignored", CMD_REF(list), "[PATH]",
     N_("Lists workspace files that do not belong to the current branch"),
     "",
     options::opts::depth | options::opts::exclude)
@@ -836,7 +836,7 @@ CMD(missing, "missing", "", CMD_REF(list
 }
 
 
-CMD(changed, "changed", "", CMD_REF(list), "",
+CMD(changed, "changed", "", CMD_REF(list), "[PATH...]",
     N_("Lists files that have changed with respect to the current revision"),
     "",
     options::opts::depth | options::opts::exclude)
============================================================
--- simplestring_xform.cc	de3c230648303fb799bdd907bb90985d2ed7e97a
+++ simplestring_xform.cc	e779da92dc0c8e2f09d5800d26073d4d2ca5d130
@@ -60,22 +60,15 @@ void split_into_lines(string const & in,
 
 void split_into_lines(string const & in,
                       vector<string> & out,
-                      bool diff_compat)
+                      split_flags::split_flags flags)
 {
-  return split_into_lines(in, constants::default_encoding, out, diff_compat);
+  return split_into_lines(in, constants::default_encoding, out, flags);
 }
 
 void split_into_lines(string const & in,
                       string const & encoding,
-                      vector<string> & out)
-{
-  return split_into_lines(in, encoding, out, false);
-}
-
-void split_into_lines(string const & in,
-                      string const & encoding,
                       vector<string> & out,
-                      bool diff_compat)
+                      split_flags::split_flags flags)
 {
   string lc_encoding = lowercase(encoding);
   out.clear();
@@ -105,13 +98,22 @@ void split_into_lines(string const & in,
 
       while (end != string::npos && end >= begin)
         {
-          out.push_back(in.substr(begin, end-begin));
+          string::size_type next_begin;
+
           if (in.at(end) == '\r'
               && in.size() > end+1
               && in.at(end+1) == '\n')
-            begin = end + 2;
+            next_begin = end + 2;
           else
-            begin = end + 1;
+            next_begin = end + 1;
+
+          if (flags & split_flags::keep_endings)
+            out.push_back(in.substr(begin, next_begin-begin));
+          else
+            out.push_back(in.substr(begin, end-begin));
+
+          begin = next_begin;
+
           if (begin >= in.size())
             break;
           end = in.find_first_of("\r\n", begin);
@@ -119,7 +121,7 @@ void split_into_lines(string const & in,
       if (begin < in.size()) {
         // special case: last line without trailing newline
         string s = in.substr(begin, in.size() - begin);
-        if (diff_compat) {
+        if (flags & split_flags::diff_compat) {
           // special handling: produce diff(1) compatible output
           s += (in.find_first_of("\r") != string::npos ? "\r\n" : "\n");
           s += "\\ No newline at end of file";
@@ -134,12 +136,6 @@ void split_into_lines(string const & in,
 }
 
 
-void
-split_into_lines(string const & in,
-                 vector<string> & out)
-{
-  split_into_lines(in, constants::default_encoding, out);
-}
 
 void
 join_lines(vector<string> const & in,
============================================================
--- simplestring_xform.hh	fb077a97ed6338787a652441b97c809750aac454
+++ simplestring_xform.hh	ab0d125445f13982344bbe3f713e2ce90d11cb66
@@ -15,21 +15,23 @@ std::string lowercase(std::string const 
 std::string uppercase(std::string const & in);
 std::string lowercase(std::string const & in);
 
-void split_into_lines(std::string const & in,
-                      std::vector<std::string> & out);
+namespace split_flags
+{
+  enum split_flags {
+    none = 0,
+    diff_compat = 1,
+    keep_endings = 2
+  };
+}
 
 void split_into_lines(std::string const & in,
-                      std::string const & encoding,
-                      std::vector<std::string> & out);
-
-void split_into_lines(std::string const & in,
                       std::vector<std::string> & out,
-                      bool diff_compat);
+                      split_flags::split_flags flags = split_flags::none);
 
 void split_into_lines(std::string const & in,
                       std::string const & encoding,
                       std::vector<std::string> & out,
-                      bool diff_compat);
+                      split_flags::split_flags flags = split_flags::none);
 
 void join_lines(std::vector<std::string> const & in,
                 std::string & out,
============================================================
--- tests/workspace_migration/twoparent-2/testfile	a9c24589987aa6b2771ec6d8a419499a563bfa31
+++ tests/workspace_migration/twoparent-2/testfile	ee18013e989404cbf57ff0af6db2a6c7ed17299d
@@ -1,2 +1,2 @@ left
 left
-right
+right
\ No newline at end of file
============================================================
--- tests/resolve_conflicts_content/__driver__.lua	00570ab4eeccfc248746cca7ffada958461d4102
+++ tests/resolve_conflicts_content/__driver__.lua	1b10a05d8783432462a1af35c855035d59383361
@@ -81,7 +81,7 @@ check(readfile("files/foo") == "foo\nmer
 check(samefilestd("update-1", "stderr"))
 
 check(readfile("files/foo") == "foo\nmerged\nrevision")
-check(readfile("files/bar") == "bar\nzero\none\ntwo\nthree\nfour\n")
+check(readfile("files/bar") == "bar\nzero\none\ntwo\nthree\nfour")
 check(readfile("files/baz") == "baz\nAaa\nBbb\nCcc")
 check(readfile("files/inter1") == "files/inter1")
 check(readfile("files/inter2") == "files/inter2")
============================================================
--- tests/resolve_conflicts_content/merge-1	bb23ecbb7f05a2de91d69a101ef6df827173c202
+++ tests/resolve_conflicts_content/merge-1	0a6aa4e9b65e60ab29cdd4c6467e9c4e7cc51dd4
@@ -5,4 +5,4 @@ mtn: replacing content of files/inter2, 
 mtn: replacing content of files/foo, files/foo with files/foo
 mtn: replacing content of files/inter1, files/inter1 with _MTN/resolutions/files/inter1
 mtn: replacing content of files/inter2, files/inter2 with _MTN/resolutions/inter_merged
-mtn: [merged] bd6a2c0363cab1cf19220bce150c77b84b1a5a32
+mtn: [merged] b221355d26015cd04668aa4587cff8068e4646a2
============================================================
--- tests/resolve_conflicts_content/update-1	2db72e362d04f0510378fc7b364d9cc6d1bc7e9f
+++ tests/resolve_conflicts_content/update-1	d46c485d67feccba79540fc6cd164d963ffdf500
@@ -1,9 +1,9 @@ mtn: updating along branch 'testbranch'
 mtn: updating along branch 'testbranch'
-mtn: selected update target bd6a2c0363cab1cf19220bce150c77b84b1a5a32
+mtn: selected update target b221355d26015cd04668aa4587cff8068e4646a2
 mtn: [left]  a047a11aae2e43f05171d8ffd8bbfde054f8a4f5
-mtn: [right] bd6a2c0363cab1cf19220bce150c77b84b1a5a32
+mtn: [right] b221355d26015cd04668aa4587cff8068e4646a2
 mtn: updating files/bar
 mtn: updating files/baz
 mtn: updating files/inter1
 mtn: updating files/inter2
-mtn: updated to base revision bd6a2c0363cab1cf19220bce150c77b84b1a5a32
+mtn: updated to base revision b221355d26015cd04668aa4587cff8068e4646a2
============================================================
--- tests/automate_file_merge/__driver__.lua	b3f8fc5291e23981a76c9c30352978ae1127d488
+++ tests/automate_file_merge/__driver__.lua	15a2032d1312df8460a20bcbcfb54d995a02ad49
@@ -3,22 +3,22 @@ addfile("foo", "foo")
 mtn_setup()
 
 addfile("foo", "foo")
-addfile("bar", "bar\none\ntwo\nthree")
-addfile("baz", "baz\naaa\nbbb\nccc")
+addfile("bar", "bar\none\ntwo\nthree\n")
+addfile("baz", "baz\r\naaa\r\nbbb\r\nccc")
 commit("testbranch", "base")
 base = base_revision()
 
 writefile("foo", "foo\nfirst\nrevision")
-writefile("bar", "bar\nzero\none\ntwo\nthree")
-writefile("baz", "baz\nAAA\nbbb\nccc")
+writefile("bar", "bar\nzero\none\ntwo\nthree\n")
+writefile("baz", "baz\r\nAAA\r\nbbb\r\nccc")
 commit("testbranch", "first")
 first = base_revision()
 
 revert_to(base)
 
 writefile("foo", "foo\nsecond\nrevision")
-writefile("bar", "bar\none\ntwo\nthree\nfour")
-writefile("baz", "baz\naaa\nbbb\nCCC")
+writefile("bar", "bar\none\ntwo\nthree\nfour\n")
+writefile("baz", "baz\r\naaa\r\nbbb\r\nCCC")
 commit("testbranch", "second")
 second = base_revision()
 
@@ -30,7 +30,7 @@ check(samefile("expected_bar", "stdout")
 canonicalize("stdout")
 check(samefile("expected_bar", "stdout"))
 
-writefile("expected_baz", "baz\nAAA\nbbb\nCCC\n")
+writefile("expected_baz", "baz\r\nAAA\r\nbbb\r\nCCC")
 check(mtn("automate", "file_merge", first, "baz", second, "baz"), 0, true, nil)
 canonicalize("stdout")
 check(samefile("expected_baz", "stdout"))
============================================================
--- database.cc	c4d5eb755d893255d1be35276e2b12ccbea8372c
+++ database.cc	9b6b20b6b342f4294e9e9d6cfd42d228db7ad18f
@@ -5029,8 +5029,11 @@ database_path_helper::validate_and_clean
   E(pure_alias.size() > 0, origin::system,
     F("invalid database alias '%s': must not be empty") % alias);
 
-  size_t pos = pure_alias.rfind('.');
-  if (pos == string::npos || pure_alias.substr(pos + 1) != "mtn")
+  globish matcher;
+  E(lua.hook_get_default_database_glob(matcher),
+    origin::user, F("could not query default database glob"));
+
+  if (!matcher.matches(pure_alias))
     pure_alias += ".mtn";
 
   try
============================================================
--- lua_hooks.cc	a71ded3aabcde9e0ef7281b7c56f2ff1fa6baaec
+++ lua_hooks.cc	a4d6c802bf0190bb5e2223219ea29b2830c7f424
@@ -723,6 +723,20 @@ bool lua_hooks::hook_get_default_databas
   return ll.ok();
 }
 
+bool lua_hooks::hook_get_default_database_glob(globish & out)
+{
+   string glob;
+   bool exec_ok
+     = Lua(st)
+     .func("get_default_database_extensions")
+     .call(0, 1)
+     .extract_str(glob)
+     .ok();
+
+  out = globish(glob, origin::user);
+  return exec_ok;
+}
+
 bool lua_hooks::hook_hook_wrapper(string const & func_name,
                                   vector<string> const & args,
                                   string & out)
============================================================
--- lua_hooks.hh	66b79c7d1dcefed2d3530e71474346b72417fee9
+++ lua_hooks.hh	325fd5a4b588ff4d41e3cec69cbf652089a33fa9
@@ -136,6 +136,8 @@ public:
 
   bool hook_get_default_database_locations(vector<system_path> & out);
 
+  bool hook_get_default_database_glob(globish & out);
+
   // workspace hooks
   bool hook_use_inodeprints();
 
============================================================
--- monotone.texi	f5888ea220ab4b3eae171fb987c5b50eb6b532e4
+++ monotone.texi	158f3a46762c3b3a5f7d6eecabcd843520706e74
@@ -6367,13 +6367,6 @@ @section Informative
 Specifying only the pathname "." will restrict the search for missing
 files to the current subdirectory of the workspace.
 
address@hidden mtn list vars address@hidden
address@hidden mtn ls vars
address@hidden vars} is an alias for @command{list vars}.
-
-This command lists all vars in your database, or all vars within a given
address@hidden  See @ref{Vars} for more information.
-
 @item mtn list tags address@hidden address@hidden
 @itemx mtn ls tags
 @command{ls tags} is an alias for @command{list tags}.
@@ -6398,6 +6391,22 @@ @section Informative
 Specifying only the pathname "." will restrict the search for unknown
 files to the current subdirectory of the workspace.
 
address@hidden mtn list vars address@hidden
address@hidden mtn ls vars
address@hidden vars} is an alias for @command{list vars}.
+
+This command lists all vars in your database, or all vars within a given
address@hidden  See @ref{Vars} for more information.
+
address@hidden mtn list workspaces
address@hidden mtn ls workspaces
address@hidden workspaces} is an alias for @command{list workspaces}.
+
+This command shows all registered workspaces for a database, be it
+managed or unmanaged.  If no database is given explicitely, defaults to
+the workspace' database in which the command is executed.
+See @ref{Managed Databases} and @ref{mtn register_workspace} for more information.
+
 @anchor{mtn address@hidden mtn log
 @itemx mtn log address@hidden address@hidden address@hidden [...]] [--clear-from] address@hidden [...]] [--clear-to] address@hidden [...]] [--[no-]brief] [--[no-]merges] [--[no-]files] [--[no-]graph] [--[no-]diffs] address@hidden
 See the online help for more options.
============================================================
--- std_hooks.lua	b1a61ba83a6e8c0c9d72393aaf0e86089b75464d
+++ std_hooks.lua	78fd8d92d19d3369b8af5809d4bda43f859e8e5e
@@ -1120,9 +1120,9 @@ function _get_netsync_read_permitted(bra
       end elseif item.name == "continue" then if state["matches"] then
          state["cont"] = true
          for j, val in pairs(item.values) do
-            if val == "false" or val == "no" then 
-	       state["cont"] = false
-	    end
+            if val == "false" or val == "no" then
+              state["cont"] = false
+            end
          end
       end elseif item.name ~= "comment" then
          io.stderr:write("unknown symbol in read-permissions: " .. item.name .. "\n")
@@ -1143,10 +1143,10 @@ function get_netsync_read_permitted(bran
       local files = read_directory(permdirname)
       table.sort(files)
       for _,f in ipairs(files) do
-	 pf = permdirname.."/"..f
-	 if _get_netsync_read_permitted(branch, ident, pf, state) then
-	    return true
-	 end
+        pf = permdirname.."/"..f
+        if _get_netsync_read_permitted(branch, ident, pf, state) then
+          return true
+        end
       end
    end
    return false
@@ -1179,8 +1179,8 @@ function get_netsync_write_permitted(ide
       local files = read_directory(permdirname)
       table.sort(files)
       for _,f in ipairs(files) do
-	 pf = permdirname.."/"..f
-	 if _get_netsync_write_permitted(ident, pf) then return true end
+        pf = permdirname.."/"..f
+        if _get_netsync_write_permitted(ident, pf) then return true end
       end
    end
    return false
@@ -1304,6 +1304,10 @@ end
     return paths
 end
 
+function get_default_database_extensions()
+    return "*.{mtn,db}"
+end
+
 hook_wrapper_dump                = {}
 hook_wrapper_dump.depth          = 0
 hook_wrapper_dump._string        = function(s) return string.format("%q", s) end
============================================================
--- work.cc	304b3f0ad0624464b9b16b23d0dcb78b4a8effb2
+++ work.cc	3c717e59b3acf99ee9cdb49ff688cad9e11472f3
@@ -657,17 +657,14 @@ workspace::set_options(options const & o
       system_path current_workspace;
       get_current_workspace(current_workspace);
 
-      if (cur_opts.dbname_type == managed_db)
+      if (cur_opts.dbname_given)
         {
           database old_db(cur_opts, lua);
           old_db.unregister_workspace(current_workspace);
         }
 
-      if (opts.dbname_type == managed_db)
-        {
-          database new_db(opts, lua);
-          new_db.register_workspace(current_workspace);
-        }
+      database new_db(opts, lua);
+      new_db.register_workspace(current_workspace);
 
       cur_opts.dbname_type = opts.dbname_type;
       cur_opts.dbname_alias = opts.dbname_alias;
============================================================
--- cmd_list.cc	1c449f70b7633a20c1caf2f284494b9959ff0ca9
+++ cmd_list.cc	f706db0c8374b743160e1ac88cbd863f67f0b2b3
@@ -44,6 +44,7 @@ using std::copy;
 using std::set;
 using std::sort;
 using std::copy;
+using std::ostream;
 using std::string;
 using std::vector;
 
@@ -614,6 +615,64 @@ CMD(vars, "vars", "", CMD_REF(list), "[D
     }
 }
 
+static void
+print_workspace_info(database & db, lua_hooks & lua,
+                     ostream & out, string const & indent = string())
+{
+  bool has_valid_workspaces = false;
+
+  vector<system_path> workspaces;
+  db.get_registered_workspaces(workspaces);
+  system_path db_path = db.get_filename();
+
+  database_path_helper helper(lua);
+  for (vector<system_path>::const_iterator k = workspaces.begin();
+       k != workspaces.end(); ++k)
+    {
+      system_path workspace_path(*k);
+      if (!directory_exists(workspace_path / bookkeeping_root_component))
+        {
+          L(FL("ignoring missing workspace '%s'") % workspace_path);
+          continue;
+        }
+
+      options workspace_opts;
+      workspace::get_options(workspace_path, workspace_opts);
+
+      system_path workspace_db_path;
+      helper.get_database_path(workspace_opts, workspace_db_path);
+
+      if (workspace_db_path != db_path)
+        {
+          L(FL("ignoring workspace '%s', expected database %s, "
+               "but has %s configured in _MTN/options")
+              % workspace_path % db_path % workspace_db_path);
+          continue;
+        }
+
+      has_valid_workspaces = true;
+
+      string workspace_branch = workspace_opts.branch();
+      if (!workspace_opts.branch_given)
+        workspace_branch = _("<no branch set>");
+
+      out << indent << F("%s (in %s)") % workspace_branch % workspace_path << '\n';
+    }
+
+    if (!has_valid_workspaces)
+      out << indent << F("no known valid workspaces") << '\n';
+}
+
+CMD(workspaces, "workspaces", "", CMD_REF(list), "",
+    N_("Lists known workspaces of a specified database"),
+    "",
+    options::opts::none)
+{
+  database db(app.opts, app.lua);
+  db.ensure_open();
+  print_workspace_info(db, app.lua, cout);
+}
+
 CMD(databases, "databases", "dbs", CMD_REF(list), "",
     N_("Lists managed databases and their known workspaces"),
     "",
@@ -621,10 +680,12 @@ CMD(databases, "databases", "dbs", CMD_R
 {
   vector<system_path> search_paths, files, dirs;
 
-  E(app.lua.hook_get_default_database_locations(search_paths), origin::database,
+  E(app.lua.hook_get_default_database_locations(search_paths), origin::user,
     F("could not query default database locations"));
 
-  database_path_helper helper(app.lua);
+  globish file_matcher;
+  E(app.lua.hook_get_default_database_glob(file_matcher), origin::user,
+    F("could not query default database glob"));
 
   for (vector<system_path>::const_iterator i = search_paths.begin();
        i != search_paths.end(); ++i)
@@ -642,19 +703,22 @@ CMD(databases, "databases", "dbs", CMD_R
 
           // a little optimization, so we don't scan and open every file
           string p = db_path.as_internal();
-          if (p.size() < 4 || p.substr(p.size() - 4) != ".mtn")
+          if (!file_matcher.matches(p))
             {
               L(FL("ignoring file '%s'") % db_path);
               continue;
             }
 
-          options opts;
-          opts.dbname_type = unmanaged_db;
-          opts.dbname = db_path;
-          opts.dbname_given = true;
+          string db_alias = ":" + db_path.as_internal().substr(
+            search_path.as_internal().size() + 1
+          );
 
-          database db(opts, app.lua);
+          options db_opts;
+          db_opts.dbname_type = managed_db;
+          db_opts.dbname_alias = db_alias;
+          db_opts.dbname_given = true;
 
+          database db(db_opts, app.lua);
           try
             {
               db.ensure_open();
@@ -672,51 +736,8 @@ CMD(databases, "databases", "dbs", CMD_R
               continue;
             }
 
-          string managed_path = db_path.as_internal().substr(
-              search_path.as_internal().size() + 1
-          );
-          cout << F(":%s (in %s):") % managed_path % search_path << '\n';
-
-          bool has_valid_workspaces = false;
-
-          vector<system_path> workspaces;
-          db.get_registered_workspaces(workspaces);
-
-          for (vector<system_path>::const_iterator k = workspaces.begin();
-               k != workspaces.end(); ++k)
-            {
-              system_path workspace_path(*k);
-              if (!directory_exists(workspace_path / bookkeeping_root_component))
-                {
-                  L(FL("ignoring missing workspace '%s'") % workspace_path);
-                  continue;
-                }
-
-              options workspace_opts;
-              workspace::get_options(workspace_path, workspace_opts);
-
-              system_path workspace_db_path;
-              helper.get_database_path(workspace_opts, workspace_db_path);
-
-              if (workspace_db_path != db_path)
-                {
-                  L(FL("ignoring workspace '%s', expected database %s, "
-                       "but has %s configured in _MTN/options")
-                      % workspace_path % db_path % workspace_db_path);
-                  continue;
-                }
-
-              has_valid_workspaces = true;
-
-              string workspace_branch = workspace_opts.branch();
-              if (!workspace_opts.branch_given)
-                workspace_branch = _("<no branch set>");
-
-              cout << F("\t%s (in %s)") % workspace_branch % workspace_path << '\n';
-            }
-
-            if (!has_valid_workspaces)
-              cout << F("\tno known valid workspaces") << '\n';
+            cout << F("%s (in %s):") % db_alias % search_path << "\n";
+            print_workspace_info(db, app.lua, cout, "\t");
         }
     }
 }
============================================================
--- tests/list_databases/__driver__.lua	c63bada5754b3e950bdfb29afdd2cb057c5290b2
+++ tests/list_databases/__driver__.lua	d78cd923f7f4950590407127854dcd3467b85625
@@ -34,3 +34,6 @@ check(qgrep("\ttest.foo.branch.+in.+list
 check(not qgrep("\tno known valid workspaces", "stdout"))
 check(qgrep("\ttest.foo.branch.+in.+list_databases\/test_foo", "stdout"))
 
+check(rename("managed_databases/bar.mtn", "managed_databases/bar.db"))
+check(mt("ls", "dbs"), 0, true, false)
+check(qgrep(":bar.db.+in.+list_databases\/managed_databases", "stdout"))
============================================================
--- /dev/null	
+++ tests/list_workspaces/__driver__.lua	d7cc622b5a893fd344653512a434440082dbc247
@@ -0,0 +1,26 @@
+
+check(raw_mtn("ls", "workspaces"), 1, false, true)
+check(qgrep("no database specified", "stderr"))
+
+check(raw_mtn("db", "init", "-d", "test.mtn"), 0, false, false)
+
+check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
+check(samelines("stdout", {"no known valid workspaces"}))
+
+check(raw_mtn("setup", "-d", "test.mtn", "-b", "test.branch1", "work1"), 0, false, false)
+
+check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
+check(qgrep("test.branch1.+in.+list_workspaces\/work1", "stdout"))
+
+check(raw_mtn("setup", "-d", "test.mtn", "-b", "test.branch2", "work2"), 0, false, false)
+check(rename("work1", "work3"))
+
+check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
+check(qgrep("test.branch2.+in.+list_workspaces\/work2", "stdout"))
+check(not qgrep("test.branch1.+in.+list_workspaces\/work1", "stdout"))
+
+check(indir("work3", raw_mtn("register_workspace", "-d", "../test.mtn")), 0, false, false)
+
+check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
+check(qgrep("test.branch1.+in.+list_workspaces\/work3", "stdout"))
+

reply via email to

[Prev in Thread] Current Thread [Next in Thread]