# # # add_dir "tests/import" # # add_file "tests/import/__driver__.lua" # content [138fe4a4f128d8765e5835d77f9472268b4cde6c] # # patch "ChangeLog" # from [3b588046694a935d1318e6608a49cda01192efcd] # to [368ef654e3d2b25df0446a0d9900d07276e3ba61] # # patch "cmd_ws_commit.cc" # from [60d05f94f72135b5fc1ef2227cf0883086163a7f] # to [b7d04c46e8220574dcaae13a78978f66e5d6da98] # # patch "monotone.texi" # from [a64ba7cfb8dff4c7a256dc6686296deff07497f8] # to [50892bd3b73bfb3b07a54ebc4de67ff8b32e51d9] # # patch "po/sv.po" # from [32963e1f453554235f152bb43e5f9e1dda26e318] # to [b59e3c2e65045dded637a3e8cfb711a1959baa40] # # patch "testsuite.lua" # from [6586c50e0f73ac0e200f0b0bac97f087da9543c1] # to [ffa13b93a3a22ca9f21777398e719a8273a01f34] # ============================================================ --- tests/import/__driver__.lua 138fe4a4f128d8765e5835d77f9472268b4cde6c +++ tests/import/__driver__.lua 138fe4a4f128d8765e5835d77f9472268b4cde6c @@ -0,0 +1,102 @@ +mtn_setup() + +mkdir("importdir") + +------------------------------------------------------------------------------ +-- First attempt, import something completely fresh. +writefile("importdir/importmefirst", "version 0 of first test file\n") + +check(mtn("import", "importdir", + "--message", "Import one, fresh start", + "--branch", "importbranch"), 0, false, false) + +check(mtn("checkout", "exportdir1", "--branch", "importbranch"), + 0, false, false) + +check(samefile("importdir/importmefirst", "exportdir1/importmefirst")) + +------------------------------------------------------------------------------ +-- Second attempt, import something with a changed file. +writefile("importdir/importmefirst", "version 1 of first test file\n") + +check(mtn("import", "importdir", + "--message", "Import two, a changed file", + "--branch", "importbranch"), 0, false, false) + +check(mtn("checkout", "exportdir2", "--branch", "importbranch"), + 0, false, false) + +check(samefile("importdir/importmefirst", "exportdir2/importmefirst")) + +------------------------------------------------------------------------------ +-- Third attempt, import something with an added file. +writefile("importdir/importmesecond", "version 0 of second test file\n") + +check(mtn("import", "importdir", + "--message", "Import three, an added file", + "--branch", "importbranch"), 0, false, false) + +check(mtn("checkout", "exportdir3", "--branch", "importbranch"), + 0, false, false) +check(mtn("automate", "heads", "importbranch"), 0, true, false) +rsha1 = trim(readfile("stdout")) + +check(samefile("importdir/importmefirst", "exportdir3/importmefirst")) +check(samefile("importdir/importmesecond", "exportdir3/importmesecond")) + +------------------------------------------------------------------------------ +-- Fourth attempt, import something with a changed and a dropped file. +remove("importdir/importmefirst") +writefile("importdir/importmesecond", "version 1 of second test file\n") + +check(mtn("import", "importdir", + "--message", "Import four, a changed and a dropped file", + "--branch", "importbranch"), 0, false, false) + +check(mtn("checkout", "exportdir4", "--branch", "importbranch"), + 0, false, false) + +check(not exists("exportdir4/importmefirst")) +check(samefile("importdir/importmesecond", "exportdir4/importmesecond")) + +------------------------------------------------------------------------------ +-- Fifth attempt, this time adding a third file and importing relative to +-- an earlier revision +writefile("importdir/importmethird", "version 0 of third test file\n") + +check(mtn("import", "importdir", + "--message", "Import five, an added file and relative to a specific revision", + "--revision", rsha1), 0, false, true) +rsha2 = string.gsub(readfile("stderr"), + "^.*committed revision ([0-9a-f]+).*$", "%1") + +check(mtn("checkout", "exportdir5", "--revision", rsha2), + 0, false, false) + +check(not exists("exportdir5/importmefirst")) +check(samefile("importdir/importmesecond", "exportdir5/importmesecond")) +check(samefile("importdir/importmethird", "exportdir5/importmethird")) + +------------------------------------------------------------------------------ +-- Sixth attempt, dropping a file and. +-- Trying again against the head of the branch. Since there's a fork, +-- this attempt is expected to FAIL. +remove("importdir/importmesecond") + +check(mtn("import", "importdir", + "--message", "Import six, an dropped file and relative to the heads", + "--branch", "importbranch"), 1, false, false) + +-- Let's do a merge and try again. +check(mtn("merge", "--branch", "importbranch"), 0, false, false) + +check(mtn("import", "importdir", + "--message", "Import six, an dropped file and relative to the heads", + "--branch", "importbranch"), 0, false, false) + +check(mtn("checkout", "exportdir6", "--branch", "importbranch"), + 0, false, false) + +check(not exists("exportdir6/importmefirst")) +check(not exists("exportdir6/importmesecond")) +check(samefile("importdir/importmethird", "exportdir6/importmethird")) ============================================================ --- ChangeLog 3b588046694a935d1318e6608a49cda01192efcd +++ ChangeLog 368ef654e3d2b25df0446a0d9900d07276e3ba61 @@ -1,3 +1,17 @@ +2006-11-30 Richard Levitte + + * cmd_ws_commit.cc (CMD_NO_WORKSPACE(import)): Add import command. + It's quite simplistic, it basically creates a _MTN bookkeeping + directory filled with information derived from a given branch or + revision, then does the following: + mtn add --unknown + mtn drop --missing + mtn commit + It will refuse to import from a workspace. + * po/sv.po: Adjust for the added and changed strings. + * tests/import/__driver__.lua, testsuite.lua: Test it. + * monotone.texi: Document it. + 2006-11-28 Christian Ohler Fix automate bug where input would be garbled if a string needed ============================================================ --- cmd_ws_commit.cc 60d05f94f72135b5fc1ef2227cf0883086163a7f +++ cmd_ws_commit.cc b7d04c46e8220574dcaae13a78978f66e5d6da98 @@ -945,6 +945,92 @@ CMD_NO_WORKSPACE(setup, N_("tree"), N_(" app.work.put_work_rev(rev); } +CMD_NO_WORKSPACE(import, N_("tree"), N_("DIRECTORY"), + N_("import the contents of the given directory tree into a given branch"), + options::opts::branch | options::opts::revision | options::opts::message) +{ + revision_id ident; + system_path dir; + + N(args.size() == 1, + F("you must specify a directory to import")); + + if (app.opts.revision_selectors.size() == 1) + { + // use specified revision + complete(app, idx(app.opts.revision_selectors, 0)(), ident); + N(app.db.revision_exists(ident), + F("no such revision '%s'") % ident); + + cert_value b; + guess_branch(ident, app, b); + + I(!app.opts.branch_name().empty()); + cert_value branch_name(app.opts.branch_name()); + base64 branch_encoded; + encode_base64(branch_name, branch_encoded); + + vector< revision > certs; + app.db.get_revision_certs(ident, branch_cert_name, branch_encoded, certs); + + L(FL("found %d %s branch certs on revision %s") + % certs.size() + % app.opts.branch_name + % ident); + + N(certs.size() != 0, F("revision %s is not a member of branch %s") + % ident % app.opts.branch_name); + } + else + { + // use branch head revision + N(!app.opts.branch_name().empty(), + F("use --revision or --branch to specify what to checkout")); + + set heads; + get_branch_heads(app.opts.branch_name(), app, heads); + if (heads.size() > 1) + { + P(F("branch %s has multiple heads:") % app.opts.branch_name); + for (set::const_iterator i = heads.begin(); i != heads.end(); ++i) + P(i18n_format(" %s") % describe_revision(app, *i)); + P(F("choose one with '%s checkout -r'") % ui.prog_name); + E(false, F("branch %s has multiple heads") % app.opts.branch_name); + } + if (heads.size() > 0) + ident = *(heads.begin()); + } + + dir = system_path(idx(args, 0)); + require_path_is_directory + (dir, + F("import directory '%s' doesn't exists") % dir, + F("import directory '%s' is a file") % dir); + + app.create_workspace(dir); + + revision_t rev; + make_revision_for_workspace(ident, cset(), rev); + app.work.put_work_rev(rev); + + vector empty_args; + // add --unknown + app.opts.unknown = true; + process(app, "add", empty_args); + app.opts.unknown = false; + + // drop --missing + app.opts.missing = true; + process(app, "drop", empty_args); + app.opts.missing = false; + + // commit + process(app, "commit", empty_args); + + // clean up + delete_dir_recursive(bookkeeping_root); +} + CMD_NO_WORKSPACE(migrate_workspace, N_("tree"), N_("[DIRECTORY]"), N_("migrate a workspace directory's metadata to the latest format; " "defaults to the current workspace"), ============================================================ --- monotone.texi a64ba7cfb8dff4c7a256dc6686296deff07497f8 +++ monotone.texi 50892bd3b73bfb3b07a54ebc4de67ff8b32e51d9 @@ -4132,6 +4132,16 @@ @section Tree both projects nested as in @var{destbranch} instead of only the project originally in @var{sourcebranch}, which is almost certainly not what would be intended. + address@hidden mtn import address@hidden address@hidden @var{dir} address@hidden mtn import address@hidden address@hidden @var{dir} +This command imports the contents of the given directory and commits it +to the head of the given branch or as a child of the given revision (and +consequently into the branch that revision resides in). + +If the given branch doesn't exist, it is created automatically. If the +branch already exists, any missing files are dropped and any unknown +files are added before commiting. @end ftable ============================================================ --- po/sv.po 32963e1f453554235f152bb43e5f9e1dda26e318 +++ po/sv.po b59e3c2e65045dded637a3e8cfb711a1959baa40 @@ -146,8 +146,8 @@ msgstr "" msgstr "" "Project-Id-Version: monotone 0.26pre1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2006-11-20 14:39+0100\n" -"PO-Revision-Date: 2006-11-20 14:40+0100\n" +"POT-Creation-Date: 2006-11-30 15:44+0100\n" +"PO-Revision-Date: 2006-11-30 15:46+0100\n" "Last-Translator: Joel Rosdahl \n" "Language-Team: Richard Levitte \n" "MIME-Version: 1.0\n" @@ -223,7 +223,7 @@ msgstr "NY_REV [GAMMAL_REV1 [GAMMAL_REV2 msgstr "NY_REV [GAMMAL_REV1 [GAMMAL_REV2 [...]]]" #: automate.cc:398 automate.cc:486 automate.cc:711 automate.cc:942 -#: automate.cc:963 automate.cc:1249 cmd_automate.cc:78 cmd_automate.cc:333 +#: automate.cc:963 automate.cc:1249 cmd_automate.cc:78 cmd_automate.cc:332 #: cmd_list.cc:564 #, c-format msgid "no arguments needed" @@ -254,7 +254,8 @@ msgstr "REVID" #: automate.cc:1080 automate.cc:1106 automate.cc:1161 automate.cc:1163 #: cmd_db.cc:35 cmd_diff_log.cc:386 cmd_diff_log.cc:417 cmd_diff_log.cc:419 #: cmd_files.cc:138 cmd_files.cc:197 cmd_merging.cc:125 cmd_merging.cc:677 -#: cmd_merging.cc:692 cmd_merging.cc:695 cmd_ws_commit.cc:479 commands.cc:413 +#: cmd_merging.cc:692 cmd_merging.cc:695 cmd_ws_commit.cc:479 +#: cmd_ws_commit.cc:963 commands.cc:413 #, c-format msgid "no such revision '%s'" msgstr "det finns ingen revision med identiteten '%s'" @@ -395,34 +396,29 @@ msgstr "" #: cmd_automate.cc:169 #, c-format -msgid "read from client failed with error code: %d" -msgstr "läsning från klienten misslyckades med följande felkod: %d" - -#: cmd_automate.cc:170 -#, c-format msgid "Bad input to automate stdio: unexpected EOF" msgstr "Felaktigt indata till automate stdio: oväntat filslut" -#: cmd_automate.cc:198 +#: cmd_automate.cc:197 #, c-format msgid "Bad input to automate stdio: unknown start token '%c'" msgstr "felaktigt indata till automate stdio: '%c' är ett okänt nyckelord" -#: cmd_automate.cc:220 +#: cmd_automate.cc:219 #, c-format msgid "Bad input to automate stdio: expected '%c' token" msgstr "Felaktigt indata till automate stdio: nyckelordet '%c' förväntat" -#: cmd_automate.cc:345 +#: cmd_automate.cc:344 #, c-format msgid "Bad input to automate stdio: command name is missing" msgstr "Felaktigt indata till automate stdio: saknar kommandonamn" -#: cmd_automate.cc:374 +#: cmd_automate.cc:373 msgid "automation" msgstr "automatisering" -#: cmd_automate.cc:375 +#: cmd_automate.cc:374 msgid "automation interface" msgstr "automatiseringsgränssnitt" @@ -1068,7 +1064,7 @@ msgstr "[ihopslagen] %s" #: cmd_merging.cc:320 cmd_merging.cc:419 cmd_merging.cc:430 cmd_merging.cc:588 #: cmd_merging.cc:821 cmd_ws_commit.cc:439 cmd_ws_commit.cc:925 -#: cmd_ws_commit.cc:948 cmd_ws_commit.cc:962 +#: cmd_ws_commit.cc:948 cmd_ws_commit.cc:1034 cmd_ws_commit.cc:1048 msgid "tree" msgstr "träd" @@ -1620,7 +1616,7 @@ msgstr " ändrade %s" msgid " patched %s" msgstr " ändrade %s" -#: cmd_ws_commit.cc:439 cmd_ws_commit.cc:925 cmd_ws_commit.cc:948 +#: cmd_ws_commit.cc:439 cmd_ws_commit.cc:925 cmd_ws_commit.cc:1034 msgid "[DIRECTORY]" msgstr "[KATALOG]" @@ -1636,27 +1632,27 @@ msgstr "" "kommer lövet i grenen (implicit eller angiven) att hämtas. Om\n" "ingen katalog anges kommer grenens namn att användas som katalognamn." -#: cmd_ws_commit.cc:458 +#: cmd_ws_commit.cc:458 cmd_ws_commit.cc:988 #, c-format msgid "use --revision or --branch to specify what to checkout" msgstr "använd --revision eller --branch för att tala om vad som ska hämtas" -#: cmd_ws_commit.cc:466 +#: cmd_ws_commit.cc:466 cmd_ws_commit.cc:994 #, c-format msgid "branch %s has multiple heads:" msgstr "grenen %s har flera löv:" -#: cmd_ws_commit.cc:469 +#: cmd_ws_commit.cc:469 cmd_ws_commit.cc:997 #, c-format msgid "choose one with '%s checkout -r'" msgstr "välj en med '%s update -r'" -#: cmd_ws_commit.cc:470 +#: cmd_ws_commit.cc:470 cmd_ws_commit.cc:998 #, c-format msgid "branch %s has multiple heads" msgstr "grenen %s har flera löv" -#: cmd_ws_commit.cc:497 +#: cmd_ws_commit.cc:497 cmd_ws_commit.cc:981 #, c-format msgid "revision %s is not a member of branch %s" msgstr "revisionen %s är inte med i grenen %s" @@ -1783,7 +1779,30 @@ msgstr "du måste ange en gren med --bra msgid "need --branch argument for setup" msgstr "du måste ange en gren med --branch till kommandot \"setup\"" +#: cmd_ws_commit.cc:948 +msgid "DIRECTORY" +msgstr "KATALOG" + #: cmd_ws_commit.cc:949 +msgid "import the contents of the given directory tree into a given branch" +msgstr "importera innhållet av den givna katalogen till den givna grenen" + +#: cmd_ws_commit.cc:956 +#, c-format +msgid "you must specify a directory to import" +msgstr "du måste ange en katalog att importera" + +#: cmd_ws_commit.cc:1007 +#, c-format +msgid "import directory '%s' doesn't exists" +msgstr "importkatalogen '%s' finns inte" + +#: cmd_ws_commit.cc:1008 +#, c-format +msgid "import directory '%s' is a file" +msgstr "importkatalogen '%s' är en fil" + +#: cmd_ws_commit.cc:1035 msgid "" "migrate a workspace directory's metadata to the latest format; defaults to " "the current workspace" @@ -1791,7 +1810,7 @@ msgstr "" "migrera en arbetskopias metadata till det senaste formatet; nuvarande " "katalog avses om inget annat anges" -#: cmd_ws_commit.cc:962 +#: cmd_ws_commit.cc:1048 msgid "refresh the inodeprint cache" msgstr "uppdatera inodeprint-cachen" @@ -4075,6 +4094,9 @@ msgstr "denna arbetskopia är i aktuellt msgid "this workspace is in the current format, no migration is necessary." msgstr "denna arbetskopia är i aktuellt format, ingen migrering behövs." +#~ msgid "read from client failed with error code: %d" +#~ msgstr "läsning från klienten misslyckades med följande felkod: %d" + #~ msgid "PATTERN ..." #~ msgstr "MÖNSTER ..." @@ -4379,9 +4401,6 @@ msgstr "denna arbetskopia är i aktuellt #~ msgid "SRC DST" #~ msgstr "KÄLLA MÅL" -#~ msgid "DIRECTORY" -#~ msgstr "KATALOG" - #~ msgid "" #~ "Attempt to start exclusive transaction within non-exclusive transaction." #~ msgstr "" ============================================================ --- testsuite.lua 6586c50e0f73ac0e200f0b0bac97f087da9543c1 +++ testsuite.lua ffa13b93a3a22ca9f21777398e719a8273a01f34 @@ -691,3 +691,4 @@ table.insert(tests, "spawn_redirected_ho table.insert(tests, "netsync_hook_errcodes") table.insert(tests, "automate_stdio_options") table.insert(tests, "spawn_redirected_hook_helper") +table.insert(tests, "import")