# # add_file "tests/t_automate_get_file.at" # # add_file "tests/t_automate_get_manifest.at" # # add_file "tests/t_automate_get_revision.at" # # patch "ChangeLog" # from [ea8f43287b62029afd6f494d7ead08be177ae6c0] # to [2f7a3b4a2b5eb443e9fb6dbb5f4817122ba960b1] # # patch "automate.cc" # from [b110377e8696e41dda47f78a8486b649b4743c5a] # to [5b96e0ff436ae87bdb8bd25121cd53a522af80d6] # # patch "commands.cc" # from [f240a4cf1fa75ef50e3fe777705b7b8a2c973997] # to [943e10f67b3f0b4397b64e4bb2c4191857730e5c] # # patch "monotone.texi" # from [09ee3a4f65495e331edd108c1462e4681159b0e6] # to [88270b0bf2d12a85a84aa047a8735cb3cdef62e6] # # patch "tests/t_automate_get_file.at" # from [] # to [57d34789ad2ede0a5233cdc4f06d0674bb2f3816] # # patch "tests/t_automate_get_manifest.at" # from [] # to [58ea47a574d79d2409180521b88dd7a311eb918e] # # patch "tests/t_automate_get_revision.at" # from [] # to [594fa8320e2c194967de5f22386809f5c9f9cc14] # # patch "testsuite.at" # from [83e96fe5709b49088ff768740029d35924e4165e] # to [95731f659f09aadbf937e69e381bfc1c4abe8555] # ======================================================================== --- ChangeLog ea8f43287b62029afd6f494d7ead08be177ae6c0 +++ ChangeLog 2f7a3b4a2b5eb443e9fb6dbb5f4817122ba960b1 @@ -1,3 +1,15 @@ +2005-09-04 Grahame Bowland + + * automate.cc, commands.cc: add "automate get_file", + "automate get_revision" and "automate get_manifest" to + automation interface. + * monotone.texi: document new automation commands + * tests/t_automate_get_file.at, tests/t_automate_get_revision_at, + tests/t_automate_get_manifest.at: trivial testing of new + automation commands for output as specified, make sure they + do not complete IDs, make sure invalid IDs are caught. + * testsuite.at: add new tests + 2005-09-01 Timothy Brownawell * lua.cc, std_hooks.lua: use proper regexes for .mt-ignore ======================================================================== --- automate.cc b110377e8696e41dda47f78a8486b649b4743c5a +++ automate.cc 5b96e0ff436ae87bdb8bd25121cd53a522af80d6 @@ -903,6 +903,154 @@ guard.commit(); } +// Name: get_revision +// Arguments: +// 1: a revision id (optional, determined from working directory if non-existant) +// Added in: 1.0 +// Purpose: Prints changeset information for the specified revision id. +// +// There are several changes that are described; each of these is described by +// a different basic_io stanza. The first string pair of each stanza indicates the +// type of change represented. +// +// Possible values of this first value are along with an ordered list of +// basic_io formatted string pairs that will be provided are: +// +// 'old_revision' : represents a parent revision. +// format: ('old_revision', revision id) +// 'new_manifest' : represents the new manifest associated with the revision. +// format: ('new_manifest', manifest id) +// 'old_manifest' : represents a manifest associated with a parent revision. +// format: ('old_manifest', manifest id) +// 'patch' : represents a file that was modified. +// format: ('patch', filename), ('from', file id), ('to', file id) +// 'add_file' : represents a file that was added. +// format: ('add_file', filename) +// 'delete_file' : represents a file that was deleted. +// format: ('delete_file', filename) +// 'delete_dir' : represents a directory that was deleted. +// format: ('delete_dir', filename) +// 'rename_file' : represents a file that was renamed. +// format: ('rename_file', old filename), ('to', new filename) +// 'rename_dir' : represents a directory that was renamed. +// format: ('rename_dir', old filename), ('to', new filename) +// +// Output format: All stanzas are formatted by basic_io. Stanzas are seperated +// by a blank line. Values will be escaped, '\' -> '\\' and '"' -> '\"'. +// +// Error conditions: If the revision specified is unknown or invalid prints an +// error message to stderr and exits with status 1. +static void +automate_get_revision(std::vector args, + std::string const & help_name, + app_state & app, + std::ostream & output) +{ + if (args.size() > 1) + throw usage(help_name); + + revision_data dat; + revision_id ident; + + if (args.size() == 0) + { + revision_set rev; + manifest_map m_old, m_new; + + app.require_working_copy(); + calculate_unrestricted_revision(app, rev, m_old, m_new); + calculate_ident(rev, ident); + write_revision_set(rev, dat); + } + else + { + ident = revision_id(idx(args, 0)()); + N(app.db.revision_exists(ident), + F("no revision %s found in database") % ident); + app.db.get_revision(ident, dat); + } + + L(F("dumping revision %s\n") % ident); + output.write(dat.inner()().data(), dat.inner()().size()); +} + +// Name: get_manifest +// Arguments: +// 1: a manifest id (optional, determined from working directory if non-existant) +// Added in: 1.0 +// Purpose: Prints the contents of the manifest associated with the given manifest ID. +// +// Output format: One line for each file in the manifest. Each line begins with a +// 40 character file ID, followed by two space characters (' ') and then the filename. +// eg: +// 22382ac1bdffec21170a88ff2580fe39b508243f vocab.hh +// +// Error conditions: If the manifest ID specified is unknown or invalid prints an +// error message to stderr and exits with status 1. +static void +automate_get_manifest(std::vector args, + std::string const & help_name, + app_state & app, + std::ostream & output) +{ + if (args.size() > 1) + throw usage(help_name); + + manifest_data dat; + manifest_id ident; + + if (args.size() == 0) + { + revision_set rev; + manifest_map m_old, m_new; + + app.require_working_copy(); + calculate_unrestricted_revision(app, rev, m_old, m_new); + + calculate_ident(m_new, ident); + write_manifest_map(m_new, dat); + } + else + { + ident = manifest_id(idx(args, 0)()); + N(app.db.manifest_version_exists(ident), + F("no manifest version %s found in database") % ident); + app.db.get_manifest_version(ident, dat); + } + + L(F("dumping manifest %s\n") % ident); + output.write(dat.inner()().data(), dat.inner()().size()); +} + +// Name: get_file +// Arguments: +// 1: a file id +// Added in: 1.0 +// Purpose: Prints the contents of the specified file. +// +// Output format: The file contents are output without modification. +// +// Error conditions: If the file id specified is unknown or invalid prints +// an error message to stderr and exits with status 1. +static void +automate_get_file(std::vector args, + std::string const & help_name, + app_state & app, + std::ostream & output) +{ + if (args.size() != 1) + throw usage(help_name); + + file_id ident(idx(args, 0)()); + N(app.db.file_version_exists(ident), + F("no file version %s found in database") % ident); + + file_data dat; + L(F("dumping file %s\n") % ident); + app.db.get_file_version(ident, dat); + output.write(dat.inner()().data(), dat.inner()().size()); +} + void automate_command(utf8 cmd, std::vector args, std::string const & root_cmd_name, @@ -1153,6 +1301,12 @@ automate_stdio(args, root_cmd_name, app, output); else if (cmd() == "certs") automate_certs(args, root_cmd_name, app, output); + else if (cmd() == "get_revision") + automate_get_revision(args, root_cmd_name, app, output); + else if (cmd() == "get_manifest") + automate_get_manifest(args, root_cmd_name, app, output); + else if (cmd() == "get_file") + automate_get_file(args, root_cmd_name, app, output); else throw usage(root_cmd_name); } ======================================================================== --- commands.cc f240a4cf1fa75ef50e3fe777705b7b8a2c973997 +++ commands.cc 943e10f67b3f0b4397b64e4bb2c4191857730e5c @@ -3747,7 +3747,10 @@ "inventory\n" "stdio\n" "certs REV\n" - "select SELECTOR\n"), + "select SELECTOR\n" + "get_file ID\n" + "get_manifest [ID]\n" + "get_revision [ID]\n"), N_("automation interface"), OPT_NONE) { ======================================================================== --- monotone.texi 09ee3a4f65495e331edd108c1462e4681159b0e6 +++ monotone.texi 88270b0bf2d12a85a84aa047a8735cb3cdef62e6 @@ -5334,6 +5334,188 @@ @end table address@hidden monotone automate get_revision address@hidden monotone automate get_revision @var{id} + address@hidden @strong address@hidden Arguments: + +Specifying the option @var{id} argument outputs the changeset +information for the specified @var{id}. Otherwise, @var{id} is +determined from the working directory. + address@hidden Added in: + +1.0 + address@hidden Purpose: + +Prints changeset information for the specified revision id. + +There are several changes that are described; each of these is described by +a different basic_io stanza. The first string pair of each stanza indicates the +type of change represented. + +Possible values of this first value are along with an ordered list of +basic_io formatted string pairs that will be provided are: + address@hidden +'old_revision' + represents a parent revision. + format: ('old_revision', revision id) +'new_manifest' + represents the new manifest associated with the revision. + format: ('new_manifest', manifest id) +'old_manifest' + represents a manifest associated with a parent revision. + format: ('old_manifest', manifest id) +'patch' + represents a file that was modified. + format: ('patch', filename), ('from', file id), ('to', file id) +'add_file' + represents a file that was added. + format: ('add_file', filename) +'delete_file' + represents a file that was deleted. + format: ('delete_file', filename) +'delete_dir' + represents a directory that was deleted. + format: ('delete_dir', filename) +'rename_file' + represents a file that was renamed. + format: ('rename_file', old filename), ('to', new filename) +'rename_dir' + represents a directory that was renamed. + format: ('rename_dir', old filename), ('to', new filename) address@hidden verbatim + address@hidden Sample output: + address@hidden +new_manifest [bfe2df785c07bebeb369e537116ab9bb7a4b5e19] + +old_revision [429fea55e9e819a046843f618d90674486695745] +old_manifest [b71855116f7049ac663102c0cb628653ffe316d1] + +patch "ChangeLog" + from [7dc21d3a46c6ecd94685ab21e67b131b32002f12] + to [234513e3838d423b24d5d6c98f70ce995c8bab6e] + +patch "std_hooks.lua" + from [0408707bb6b97eae7f8da61af7b35364dbd5a189] + to [d7bd0756c48ace573926197709e53eb24dae5f5f] address@hidden verbatim + address@hidden Output format: + +All stanzas are formatted by basic_io. Stanzas are seperated +by a blank line. Values will be escaped, '\' to '\\' and +'"' to '\"'. + address@hidden Error conditions: + +If the revision specified is unknown or invalid prints an error message +to stderr and exits with status 1. + address@hidden table + address@hidden monotone automate get_manifest address@hidden monotone automate get_manifest @var{id} + address@hidden @strong address@hidden Arguments: + +Specifying the optional @var{id} argument outputs the maifest for the +specified @var{id}. Otherwise, @var{id} is determined from the working +directory. + address@hidden Added in: + +1.0 + address@hidden Purpose: + +Prints the contents of the manifest associated with the given manifest ID. + address@hidden Sample output: + address@hidden +e3915658cb464d05f21332e03d30dca5d94fe776 .htaccess +00ff89c69e7a8f6a0f48c6503168d9b62a0cfeb0 .mt-attrs +80d8f3f75c9b517ec462233e155f7dfb93379f67 AUTHORS +fc74a48c7f73eedcbe1ea709755fbe819b29736c ChangeLog +dfac199a7539a404407098a2541b9482279f690d LICENSE +440eec971e7bb61ccbb61634deb2729bb25931cd README +e0ea26c666b37c5f98ccf80cb933d021ee55c593 TODO +b28ece354969314ce996f3030569215d685973d6 branch.psp +1fdb62e05fb2a9338d2c72ddc58de3ab2b3976fe common.py +64cb5898e3a026b4782c343ca4386585e0c3c275 config.py.example +7152c3ff110418aca5d23c374ea9fb92a0e98379 error.psp +5d8536100fdf51d505b6f20bc9c16aa78d4e86a8 fileinbranch.psp +981df124a0b5655a9f78c42504cfa8c6f02b267a headofbranch.psp +a43d0588a69e622b2afc681678c2a5c3b3b1f342 help.psp +18a8bffc8729d7bfd71d2e0cb35a1aed1854fa74 html.py +c621827db187839e1a7c6e51d5f1a7f6e0aa560c index.psp +708b61436dce59f47bd07397ce96a1cfabe81970 monotone.py +a02b1c161006840ea8685e461fd07f0e9bb145a3 revision.psp +027515fd4558abf317d54c437b83ec6bc76e3dd8 rss_feed.gif +638140d6823eee5844de37d985773be75707fa25 tags.psp +be83f459a152ffd49d89d69555f870291bc85311 tarofbranch.psp +fb51955563d64e628e0e67e4acca1a1abc4cd989 utility.py +8d04b3fc352a860b0e3240dcb539c1193705398f viewmtn.css +7cb5c6b1b1710bf2c0fa41e9631ae43b03424a35 viewmtn.py +530290467a99ca65f87b74f653bf462b28c6cda9 wrapper.py address@hidden verbatim + address@hidden Output format: + +The output format is one line for each file in the manifest. Each line begins +with a 40 character file ID, followed by two space characters (' ') and then +the filename. + address@hidden Error conditions: + +If the manifest ID specified is unknown or invalid prints an error +message to stderr and exits with status 1. + address@hidden table + address@hidden monotone automate get_file @var{id} + address@hidden @strong address@hidden Arguments: + +The @var{id} argument specifies the file to be output. + address@hidden Added in: + +1.0 + address@hidden Purpose: + +Prints the contents of the specified file. + address@hidden Sample output: + address@hidden +If you've downloaded a release, see INSTALL for installation +instructions. If you've checked this out, the generated files are not +included, and you must use "autoreconf --install" to create them. + +"make html" for docs, or read the .info file and / or man page. address@hidden verbatim + address@hidden Output format: + +The file contents are output without modification. + address@hidden Error conditions: + +If the file id specified is unknown or invalid prints an error message +to stderr and exits with status 1. + address@hidden table + @end ftable @page ======================================================================== --- tests/t_automate_get_file.at +++ tests/t_automate_get_file.at 57d34789ad2ede0a5233cdc4f06d0674bb2f3816 @@ -0,0 +1,35 @@ +# -*- Autoconf -*- + +AT_SETUP([automate get_file]) +NEED_UNB64 +MONOTONE_SETUP + +AT_DATA(expected, [blah +]) + +AT_DATA(empty, []) + +ADD_FILE(foo, [blah +]) +AT_CHECK(MONOTONE commit --date=2005-05-21T12:30:51 --branch=testbranch --message=blah-blah, [], [ignore], [ignore]) +BASE_R=`BASE_REVISION` +FILE_R=4cbd040533a2f43fc6691d773d510cda70f4126a + +# check that a correct usage produces correctly formatted output +AT_CHECK(MONOTONE automate get_file $FILE_R, [], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp expected stdout) + +# ensure that missing revisions fail +NOSUCHREV=0000000000000000000000000000000000000000 +AT_CHECK(MONOTONE automate get_file $NOSUCHREV, [1], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp empty stdout) + +# ensure that revisions are not being completed +TRUNCATEDREV=4cbd040533a2f43fc6691d773d510c +AT_CHECK(MONOTONE automate get_file $TRUNCATEDREV, [1], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp empty stdout) + +AT_CLEANUP ======================================================================== --- tests/t_automate_get_manifest.at +++ tests/t_automate_get_manifest.at 58ea47a574d79d2409180521b88dd7a311eb918e @@ -0,0 +1,41 @@ +# -*- Autoconf -*- + +AT_SETUP([automate get_manifest]) +NEED_UNB64 +MONOTONE_SETUP + +AT_DATA(expected, [4cbd040533a2f43fc6691d773d510cda70f4126a foo +]) + +AT_DATA(empty, []) + +ADD_FILE(foo, [blah +]) +AT_CHECK(MONOTONE commit --date=2005-05-21T12:30:51 --branch=testbranch --message=blah-blah, [], [ignore], [ignore]) +BASE_R=`BASE_REVISION` +MANIFEST_R=095e136cd6e47e3519869fb0f07dcce183780b6e + +# check that a correct usage produces correctly formatted output +AT_CHECK(MONOTONE automate get_manifest $MANIFEST_R, [], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp expected stdout) + +# should work even if we don't specify the manifest ID +AT_CHECK(MONOTONE automate get_manifest, [], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp expected stdout) + +# ensure that missing revisions fail +NOSUCHREV=0000000000000000000000000000000000000000 +AT_CHECK(MONOTONE automate get_file $NOSUCHREV, [1], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp empty stdout) + +# ensure that revisions are not being completed +# (the above commit will have created rev 306c506078df4b58470f75c845ccd11c2ea8cb26) +TRUNCATEDREV=306c506078df4b58470f75c845ccd1 +AT_CHECK(MONOTONE automate get_file $TRUNCATEDREV, [1], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp empty stdout) + +AT_CLEANUP ======================================================================== --- tests/t_automate_get_revision.at +++ tests/t_automate_get_revision.at 594fa8320e2c194967de5f22386809f5c9f9cc14 @@ -0,0 +1,55 @@ +# -*- Autoconf -*- + +AT_SETUP([automate get_manifest]) +NEED_UNB64 +MONOTONE_SETUP + +AT_DATA(expected, [new_manifest @<:@095e136cd6e47e3519869fb0f07dcce183780b6e@:>@ + +old_revision @<:@@:>@ +old_manifest @<:@@:>@ + +add_file "foo" + +patch "foo" + from @<:@@:>@ + to @<:@4cbd040533a2f43fc6691d773d510cda70f4126a@:>@ +]) + +AT_DATA(expected2, [new_manifest @<:@095e136cd6e47e3519869fb0f07dcce183780b6e@:>@ + +old_revision @<:@306c506078df4b58470f75c845ccd11c2ea8cb26@:>@ +old_manifest @<:@095e136cd6e47e3519869fb0f07dcce183780b6e@:>@ +]) + +AT_DATA(empty, []) + +ADD_FILE(foo, [blah +]) +AT_CHECK(MONOTONE commit --date=2005-05-21T12:30:51 --branch=testbranch --message=blah-blah, [], [ignore], [ignore]) +BASE_R=`BASE_REVISION` + +# check that a correct usage produces correctly formatted output +AT_CHECK(MONOTONE automate get_revision $BASE_R, [], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp expected stdout) + +# should work even if we don't specify the revision +AT_CHECK(MONOTONE automate get_revision, [], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp expected2 stdout) + +# ensure that missing revisions fail +NOSUCHREV=0000000000000000000000000000000000000000 +AT_CHECK(MONOTONE automate get_file $NOSUCHREV, [1], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp empty stdout) + +# ensure that revisions are not being completed +# (the above commit will have created rev 306c506078df4b58470f75c845ccd11c2ea8cb26) +TRUNCATEDREV=095e136cd6e47e3519869fb0f07dcc +AT_CHECK(MONOTONE automate get_file $TRUNCATEDREV, [1], [stdout], [ignore]) +AT_CHECK(CANONICALISE(stdout)) +AT_CHECK(cmp empty stdout) + +AT_CLEANUP ======================================================================== --- testsuite.at 83e96fe5709b49088ff768740029d35924e4165e +++ testsuite.at 95731f659f09aadbf937e69e381bfc1c4abe8555 @@ -700,3 +700,6 @@ m4_include(tests/t_read_from_file.at) m4_include(tests/t_setup_existing_path.at) m4_include(tests/t_mt_ignore.at) +m4_include(tests/t_automate_get_file.at) +m4_include(tests/t_automate_get_manifest.at) +m4_include(tests/t_automate_get_revision.at)