monotone.patch.rse 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. This is the RSE patchset for the Monotone VCS.
  2. The patchset is entirely enclosed in...
  3. #if defined(RSE) /* <tag> */
  4. [...]
  5. #endif
  6. ...and this way can be clearly distinguished. The <tag> corresponds
  7. the following major changes it includes:
  8. o environment-variables:
  9. This adds the two environment variables MTN_DBFILE and MTN_KEYDIR as
  10. defaults for the (bootstrapping) mtn(1) command line options --db
  11. and --keydir. This allows you to provide values for them without
  12. having to pass the options all the time.
  13. o alt-book-keeping-root:
  14. This allows mtn(1) to accept an alternative book-keeping directory.
  15. The default still is "_MTN", but alternatively one can rename this
  16. to ".mtn". If one sets the environment variable "MTN_BKROOT" one can
  17. change ".mtn" to an arbitrary sub-directory name and additionally
  18. even force its use on workspace creation operations.
  19. o cosmetics-netsync:
  20. This is just a small cosmetics change. It reduces the annoying
  21. "doing anonymous pull; use -kKEYNAME if you need authentication" to
  22. just "doing anonymous pull" as mtn(1) doesn't have to teach people.
  23. That's for what the documentation is for.
  24. o cosmetics-stat:
  25. The workspace top-level directory is shown as "" instead of nothing.
  26. o cosmetics-diff-and-log:
  27. This cosmetically "improves" the output of "mtn diff" and "mtn
  28. log". For "mtn diff" The output of "mtn diff" now uses a separator
  29. line consisting of 67 (instead of 60) "=" characters to align
  30. with cvs(1)'s well known output. Additionally, two new command
  31. line options for "mtn diff" allow one to disable some outputs:
  32. "--no-show-header" disables the output of the redundant "#..."
  33. header lines at the top of the output and "--no-show-separator"
  34. disables the output of the separator line at all. The output of "mtn
  35. log" is improved by aligning the single-line certificate values and
  36. by indenting the file change information by just 4 instead of 8
  37. characters.
  38. o diff-index:
  39. This adds "Index:" lines to the output of "mtn diff" in order to
  40. align with the "svn diff" and "cvs diff" outputs. This also helps
  41. patch(1) to clearly identify the file to patch.
  42. o extra-commands:
  43. This adds "mtn fuse", "mtn conflicts", "mtn revision" and "mtn base"
  44. commands. They are all simple but convenient Lua wrappers.
  45. o dot-mtn-message:
  46. Support a ".mtn-message" file in the root-directory as a template
  47. for the commit messages.
  48. Ralf S. Engelschall
  49. rse@engelschall.com
  50. www.engelschall.com
  51. Index: app_state.cc
  52. --- app_state.cc.orig 2007-12-12 20:45:21 +0100
  53. +++ app_state.cc 2007-12-13 08:59:14 +0100
  54. @@ -138,13 +138,24 @@
  55. go_to_workspace(new_dir);
  56. mark_std_paths_used();
  57. +#if defined(RSE) /* alt-book-keeping-root */
  58. + N(!(directory_exists(bookkeeping_root) || directory_exists(alt_bookkeeping_root)),
  59. + F("monotone bookkeeping directory '%s' or '%s' already exists in '%s'")
  60. + % bookkeeping_root % alt_bookkeeping_root % new_dir);
  61. +#else
  62. N(!directory_exists(bookkeeping_root),
  63. F("monotone bookkeeping directory '%s' already exists in '%s'")
  64. % bookkeeping_root % new_dir);
  65. +#endif
  66. L(FL("creating bookkeeping directory '%s' for workspace in '%s'")
  67. % bookkeeping_root % new_dir);
  68. +#if defined(RSE) /* alt-book-keeping-root */
  69. + if (getenv("MTN_BKROOT") != NULL)
  70. + mkdir_p(bookkeeping_path(getenv("MTN_BKROOT")));
  71. + else
  72. +#endif
  73. mkdir_p(bookkeeping_root);
  74. make_branch_sticky();
  75. Index: cmd_diff_log.cc
  76. --- cmd_diff_log.cc.orig 2007-12-12 20:45:27 +0100
  77. +++ cmd_diff_log.cc 2007-12-13 08:59:14 +0100
  78. @@ -96,6 +96,27 @@
  79. set<file_path> const & s,
  80. size_t max_cols)
  81. {
  82. +#if defined(RSE) /* cosmetics-diff-and-log */
  83. + size_t cols = 4;
  84. + os << " ";
  85. + for (set<file_path>::const_iterator i = s.begin();
  86. + i != s.end(); i++)
  87. + {
  88. + const string str = lexical_cast<string>(*i);
  89. + if (cols > 4 && cols + str.size() + 1 >= max_cols)
  90. + {
  91. + cols = 4;
  92. + os << "\n ";
  93. + }
  94. + else if (cols > 4) {
  95. + os << ' ';
  96. + cols += 1;
  97. + }
  98. + os << str;
  99. + cols += str.size();
  100. + }
  101. + os << '\n';
  102. +#else
  103. size_t cols = 8;
  104. os << " ";
  105. for (set<file_path>::const_iterator i = s.begin();
  106. @@ -113,6 +134,7 @@
  107. cols += str.size() + 1;
  108. }
  109. os << '\n';
  110. +#endif
  111. }
  112. void
  113. @@ -131,7 +153,11 @@
  114. for (map<file_path, file_path>::const_iterator
  115. i = cs.nodes_renamed.begin();
  116. i != cs.nodes_renamed.end(); i++)
  117. +#if defined(RSE) /* cosmetics-diff-and-log */
  118. + os << " " << i->first
  119. +#else
  120. os << " " << i->first
  121. +#endif
  122. << " to " << i->second << '\n';
  123. }
  124. @@ -232,8 +258,13 @@
  125. set<file_path> const & paths,
  126. bool limit_paths = false)
  127. {
  128. +#if defined(RSE) /* cosmetics-diff-and-log */
  129. + // 67 is somewhat arbitrary (CVS uses this), but less than 80
  130. + string patch_sep = string(67, '=');
  131. +#else
  132. // 60 is somewhat arbitrary, but less than 80
  133. string patch_sep = string(60, '=');
  134. +#endif
  135. for (map<file_path, file_id>::const_iterator
  136. i = cs.files_added.begin();
  137. @@ -242,6 +273,9 @@
  138. if (limit_paths && paths.find(i->first) == paths.end())
  139. continue;
  140. +#if defined(RSE) /* cosmetics-diff-and-log */
  141. + if (!app.opts.no_show_separator)
  142. +#endif
  143. output << patch_sep << '\n';
  144. data unpacked;
  145. vector<string> lines;
  146. @@ -288,6 +322,9 @@
  147. file_data f_old;
  148. data data_old, data_new;
  149. +#if defined(RSE) /* cosmetics-diff-and-log */
  150. + if (!app.opts.no_show_separator)
  151. +#endif
  152. output << patch_sep << '\n';
  153. app.db.get_file_version(delta_entry_src(i), f_old);
  154. @@ -503,6 +540,9 @@
  155. data summary;
  156. write_cset(included, summary);
  157. +#if defined(RSE) /* cosmetics-diff-and-log */
  158. + if (!app.opts.no_show_header) {
  159. +#endif
  160. vector<string> lines;
  161. split_into_lines(summary(), lines);
  162. cout << "#\n";
  163. @@ -518,6 +558,9 @@
  164. cout << "# " << _("no changes") << '\n';
  165. }
  166. cout << "#\n";
  167. +#if defined(RSE) /* cosmetics-diff-and-log */
  168. + }
  169. +#endif
  170. if (app.opts.diff_format == external_diff)
  171. {
  172. @@ -881,7 +924,11 @@
  173. else
  174. {
  175. out << string(65, '-') << '\n';
  176. +#if defined(RSE) /* cosmetics-diff-and-log */
  177. + out << "Revision: " << rid << '\n';
  178. +#else
  179. out << "Revision: " << rid << '\n';
  180. +#endif
  181. changes_summary csum;
  182. @@ -896,12 +943,21 @@
  183. for (set<revision_id>::const_iterator anc = ancestors.begin();
  184. anc != ancestors.end(); ++anc)
  185. +#if defined(RSE) /* cosmetics-diff-and-log */
  186. + out << "Ancestor: " << *anc << '\n';
  187. +
  188. + log_certs(out, app, rid, author_name, "Author: ", false);
  189. + log_certs(out, app, rid, date_name, "Date: ", false);
  190. + log_certs(out, app, rid, branch_name, "Branch: ", false);
  191. + log_certs(out, app, rid, tag_name, "Tag: ", false);
  192. +#else
  193. out << "Ancestor: " << *anc << '\n';
  194. log_certs(out, app, rid, author_name, "Author: ", false);
  195. log_certs(out, app, rid, date_name, "Date: ", false);
  196. log_certs(out, app, rid, branch_name, "Branch: ", false);
  197. log_certs(out, app, rid, tag_name, "Tag: ", false);
  198. +#endif
  199. if (!app.opts.no_files && !csum.cs.empty())
  200. {
  201. @@ -911,7 +967,11 @@
  202. }
  203. log_certs(out, app, rid, changelog_name, "ChangeLog: ", true);
  204. +#if defined(RSE) /* cosmetics-diff-and-log */
  205. + log_certs(out, app, rid, comment_name, "Comments: ", true);
  206. +#else
  207. log_certs(out, app, rid, comment_name, "Comments: ", true);
  208. +#endif
  209. }
  210. if (app.opts.diffs)
  211. Index: cmd_netsync.cc
  212. --- cmd_netsync.cc.orig 2007-12-12 20:45:28 +0100
  213. +++ cmd_netsync.cc 2007-12-13 08:59:14 +0100
  214. @@ -179,7 +179,11 @@
  215. find_key_if_needed(addr, include_pattern, exclude_pattern, app, false);
  216. if (app.opts.signing_key() == "")
  217. +#if defined(RSE) /* cosmetics-netsync */
  218. + P(F("doing anonymous pull"));
  219. +#else
  220. P(F("doing anonymous pull; use -kKEYNAME if you need authentication"));
  221. +#endif
  222. std::list<utf8> uris;
  223. uris.push_back(addr);
  224. @@ -277,7 +281,11 @@
  225. app.create_workspace(workspace_dir);
  226. if (internal_db)
  227. +#if defined(RSE) /* alt-book-keeping-root */
  228. + app.set_database(system_path((directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / ws_internal_db_file_name));
  229. +#else
  230. app.set_database(system_path(bookkeeping_root / ws_internal_db_file_name));
  231. +#endif
  232. else
  233. app.set_database(app.opts.dbname);
  234. @@ -299,7 +307,11 @@
  235. app, false);
  236. if (app.opts.signing_key() == "")
  237. +#if defined(RSE) /* cosmetics-netsync */
  238. + P(F("doing anonymous pull"));
  239. +#else
  240. P(F("doing anonymous pull; use -kKEYNAME if you need authentication"));
  241. +#endif
  242. if (!app.db.var_exists(default_include_pattern_key)
  243. || app.opts.set_default)
  244. Index: cmd_ws_commit.cc
  245. --- cmd_ws_commit.cc.orig 2007-12-12 20:45:28 +0100
  246. +++ cmd_ws_commit.cc 2007-12-13 08:59:14 +0100
  247. @@ -66,7 +66,14 @@
  248. for (set<file_path>::const_iterator i = cs.dirs_added.begin();
  249. i != cs.dirs_added.end(); ++i)
  250. +#if defined(RSE) /* cosmetics-stat */
  251. + if ((*i) == file_path())
  252. + out += (F(" added \"\"")).str() += '\n';
  253. + else
  254. + out += (F(" added %s") % *i).str() += '\n';
  255. +#else
  256. out += (F(" added %s") % *i).str() += '\n';
  257. +#endif
  258. for (map<file_path, file_id>::const_iterator i = cs.files_added.begin();
  259. i != cs.files_added.end(); ++i)
  260. @@ -1355,7 +1362,11 @@
  261. catch (...)
  262. {
  263. // clean up before rethrowing
  264. +#if defined(RSE) /* alt-book-keeping-root */
  265. + delete_dir_recursive(directory_exists(alt_bookkeeping_root) ? bookkeeping_root : bookkeeping_root);
  266. +#else
  267. delete_dir_recursive(bookkeeping_root);
  268. +#endif
  269. throw;
  270. }
  271. Index: diff_patch.cc
  272. --- diff_patch.cc.orig 2007-12-12 20:45:30 +0100
  273. +++ diff_patch.cc 2007-12-13 08:59:14 +0100
  274. @@ -1324,6 +1324,9 @@
  275. {
  276. case unified_diff:
  277. {
  278. +#if defined(RSE) /* diff-index */
  279. + ost << "Index: " << filename2 << '\n';
  280. +#endif
  281. ost << "--- " << filename1 << '\t' << id1 << '\n';
  282. ost << "+++ " << filename2 << '\t' << id2 << '\n';
  283. @@ -1333,6 +1336,9 @@
  284. }
  285. case context_diff:
  286. {
  287. +#if defined(RSE) /* diff-index */
  288. + ost << "Index: " << filename2 << '\n';
  289. +#endif
  290. ost << "*** " << filename1 << '\t' << id1 << '\n';
  291. ost << "--- " << filename2 << '\t' << id2 << '\n';
  292. Index: file_io.cc
  293. --- file_io.cc.orig 2007-12-12 20:45:31 +0100
  294. +++ file_io.cc 2007-12-13 08:59:14 +0100
  295. @@ -398,16 +398,36 @@
  296. write_data(file_path const & path, data const & dat)
  297. {
  298. // use the bookkeeping root as the temporary directory.
  299. +#if defined(RSE) /* alt-book-keeping-root */
  300. + if (directory_exists(alt_bookkeeping_root)) {
  301. + assert_path_is_directory(alt_bookkeeping_root);
  302. + write_data_impl(path, dat, alt_bookkeeping_root, false);
  303. + }
  304. + else {
  305. +#endif
  306. assert_path_is_directory(bookkeeping_root);
  307. write_data_impl(path, dat, bookkeeping_root, false);
  308. +#if defined(RSE) /* alt-book-keeping-root */
  309. + }
  310. +#endif
  311. }
  312. void
  313. write_data(bookkeeping_path const & path, data const & dat)
  314. {
  315. // use the bookkeeping root as the temporary directory.
  316. +#if defined(RSE) /* alt-book-keeping-root */
  317. + if (directory_exists(alt_bookkeeping_root)) {
  318. + assert_path_is_directory(alt_bookkeeping_root);
  319. + write_data_impl(path, dat, alt_bookkeeping_root, false);
  320. + }
  321. + else {
  322. +#endif
  323. assert_path_is_directory(bookkeeping_root);
  324. write_data_impl(path, dat, bookkeeping_root, false);
  325. +#if defined(RSE) /* alt-book-keeping-root */
  326. + }
  327. +#endif
  328. }
  329. void
  330. Index: lua_hooks.cc
  331. --- lua_hooks.cc.orig 2007-12-12 20:45:33 +0100
  332. +++ lua_hooks.cc 2007-12-13 08:59:14 +0100
  333. @@ -162,7 +162,11 @@
  334. void
  335. lua_hooks::workspace_rcfilename(bookkeeping_path & file)
  336. {
  337. +#if defined(RSE) /* alt-book-keeping-root */
  338. + file = (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / "monotonerc";
  339. +#else
  340. file = bookkeeping_root / "monotonerc";
  341. +#endif
  342. }
  343. Index: monotone.cc
  344. --- monotone.cc.orig 2007-12-12 20:45:33 +0100
  345. +++ monotone.cc 2007-12-13 08:59:14 +0100
  346. @@ -229,12 +229,28 @@
  347. if (!app.opts.dbname.empty())
  348. app.db.set_filename(app.opts.dbname);
  349. }
  350. +#if defined(RSE) /* environment-variables */
  351. + else
  352. + {
  353. + char *cp;
  354. + if ((cp = getenv("MTN_DBFILE")) != NULL)
  355. + app.db.set_filename(system_path(cp));
  356. + }
  357. +#endif
  358. if (app.opts.key_dir_given || app.opts.conf_dir_given)
  359. {
  360. if (!app.opts.key_dir.empty())
  361. app.keys.set_key_dir(app.opts.key_dir);
  362. }
  363. +#if defined(RSE) /* environment-variables */
  364. + else
  365. + {
  366. + char *cp;
  367. + if ((cp = getenv("MTN_KEYDIR")) != NULL)
  368. + app.keys.set_key_dir(system_path(cp));
  369. + }
  370. +#endif
  371. // at this point we allow a workspace (meaning search for it
  372. // and if found read _MTN/options, but don't use the data quite
  373. Index: options_list.hh
  374. --- options_list.hh.orig 2007-12-12 20:45:35 +0100
  375. +++ options_list.hh 2007-12-13 08:59:14 +0100
  376. @@ -178,6 +178,24 @@
  377. no_show_encloser = true;
  378. }
  379. #endif
  380. +#if defined(RSE) /* cosmetics-diff-and-log */
  381. +OPTVAR(diff_options, bool, no_show_header, false)
  382. +OPTION(diff_options, no_show_header, false, "no-show-header",
  383. + gettext_noop("do not show the summary header"))
  384. +#ifdef option_bodies
  385. +{
  386. + no_show_header = true;
  387. +}
  388. +#endif
  389. +OPTVAR(diff_options, bool, no_show_separator, false)
  390. +OPTION(diff_options, no_show_separator, false, "no-show-separator",
  391. + gettext_noop("do not show the separator line"))
  392. +#ifdef option_bodies
  393. +{
  394. + no_show_separator = true;
  395. +}
  396. +#endif
  397. +#endif
  398. OPT(diffs, "diffs", bool, false, gettext_noop("print diffs along with logs"))
  399. #ifdef option_bodies
  400. Index: paths.cc
  401. --- paths.cc.orig 2007-12-12 20:45:35 +0100
  402. +++ paths.cc 2007-12-13 08:59:14 +0100
  403. @@ -226,7 +226,11 @@
  404. static inline bool
  405. in_bookkeeping_dir(string const & path)
  406. {
  407. +#if defined(RSE) /* alt-book-keeping-root */
  408. + if (path.size() == 0 || (path[0] != '_' && path[0] != '.'))
  409. +#else
  410. if (path.size() == 0 || (path[0] != '_'))
  411. +#endif
  412. return false;
  413. if (path.size() == 1 || (path[1] != 'M' && path[1] != 'm'))
  414. return false;
  415. @@ -919,6 +923,9 @@
  416. // first look for the current name of the bookkeeping directory.
  417. // if we don't find it, look for it under the old name, so that
  418. // migration has a chance to work.
  419. +#if defined(RSE) /* alt-book-keeping-root */
  420. + if (!find_bookdir(root, alt_bookkeeping_root_component, current, removed))
  421. +#endif
  422. if (!find_bookdir(root, bookkeeping_root_component, current, removed))
  423. if (!find_bookdir(root, old_bookkeeping_root_component, current, removed))
  424. return false;
  425. Index: paths.hh
  426. --- paths.hh.orig 2007-12-12 20:45:35 +0100
  427. +++ paths.hh 2007-12-13 08:59:14 +0100
  428. @@ -325,6 +325,15 @@
  429. // for migration
  430. #define old_bookkeeping_root_component (path_component("MT"))
  431. +#if defined(RSE) /* alt-book-keeping-root */
  432. +#ifndef MTN_ALT_BKROOT
  433. +#define MTN_ALT_BKROOT ".mtn"
  434. +#endif
  435. +#define MTN_ALT_BKROOT_ARG (getenv("MTN_BKROOT") != NULL ? getenv("MTN_BKROOT") : MTN_ALT_BKROOT)
  436. +#define alt_bookkeeping_root (bookkeeping_path(MTN_ALT_BKROOT_ARG))
  437. +#define alt_bookkeeping_root_component (path_component(MTN_ALT_BKROOT_ARG))
  438. +#endif
  439. +
  440. // this will always be an absolute path
  441. class system_path : public any_path
  442. {
  443. Index: roster_merge.cc
  444. --- roster_merge.cc.orig 2007-12-12 20:45:37 +0100
  445. +++ roster_merge.cc 2007-12-13 08:59:14 +0100
  446. @@ -633,6 +633,20 @@
  447. result.roster.detach_node(n->self);
  448. result.illegal_name_conflicts.push_back(conflict);
  449. }
  450. +#if defined(RSE) /* alt-book-keeping-root */
  451. + if (result_root->has_child(alt_bookkeeping_root_component))
  452. + {
  453. + illegal_name_conflict conflict;
  454. + node_t n = result_root->get_child(alt_bookkeeping_root_component);
  455. + conflict.nid = n->self;
  456. + conflict.parent_name.first = n->parent;
  457. + conflict.parent_name.second = n->name;
  458. + I(n->name == alt_bookkeeping_root_component);
  459. +
  460. + result.roster.detach_node(n->self);
  461. + result.illegal_name_conflicts.push_back(conflict);
  462. + }
  463. +#endif
  464. }
  465. }
  466. Index: std_hooks.lua
  467. --- std_hooks.lua.orig 2007-12-12 20:45:39 +0100
  468. +++ std_hooks.lua 2007-12-13 10:12:23 +0100
  469. @@ -284,6 +284,15 @@
  470. if user_log_message == "" or string.sub(user_log_message, -1) ~= "\n" then
  471. tmp:write("\n")
  472. end
  473. + -- #if defined(RSE) /* dot-mtn-message */
  474. + local template_log_message = read_contents_of_file(".mtn-message", "r")
  475. + if template_log_message ~= nil then
  476. + tmp:write(template_log_message)
  477. + if template_log_message == "" or string.sub(template_log_message, -1) ~= "\n" then
  478. + tmp:write("\n")
  479. + end
  480. + end
  481. + -- #endif
  482. tmp:write(basetext)
  483. io.close(tmp)
  484. @@ -1220,4 +1229,165 @@
  485. function push_netsync_notifier(notifier)
  486. return push_hook_functions(notifier)
  487. end
  488. -end
  489. \ No newline at end of file
  490. +end
  491. +
  492. +-- #if defined(RSE) /* extra-command */
  493. +
  494. +-- extra command: "mtn fuse REVISION"
  495. +register_command(
  496. + "fuse", "REVISION",
  497. + "Fuse revision into workspace with conflict markers.",
  498. + "Fuse the specified revision into the current workspace by merging " ..
  499. + "the revision into the workspace while providing inline conflict " ..
  500. + "markers for manually resolving the conflicts in the workspace " ..
  501. + "before comitting the conflicts-resolved workspace as the new " ..
  502. + "merged revision.",
  503. + "command_fuse"
  504. +)
  505. +function command_fuse(revision)
  506. + if revision == nil then
  507. + io.stderr:write("mtn: fuse: ERROR: revision not given\n")
  508. + return
  509. + end
  510. + if program_exists_in_path("mtn") == 0 then
  511. + io.stderr:write("mtn: fuse: ERROR: require Monotone command \"mtn\" in PATH\n")
  512. + return
  513. + end
  514. + mtn_automate("get_option", "branch") -- make sure we have a valid workspace
  515. + local cmd =
  516. + "MTN_MERGE=diffutils " ..
  517. + "MTN_MERGE_DIFFUTILS=\"partial,diff3opts=-E\" " ..
  518. + "mtn " .. "merge_into_workspace " .. revision
  519. + local rc = execute("sh", "-c", cmd)
  520. + if rc ~= 0 then
  521. + io.stderr:write("mtn: fuse: ERROR: failed to execute command \"" .. cmd .. "\"\n")
  522. + end
  523. +end
  524. +
  525. +-- extra command: "mtn conflicts"
  526. +register_command(
  527. + "conflicts", "",
  528. + "Lists files in workspace containing conflict markers.",
  529. + "Lists all files in the current workspace containing the " ..
  530. + "conflict markers produced by GNU diffutils' \"diff3\" " ..
  531. + "command. This indicates still unresolved merge conflicts.",
  532. + "command_conflicts"
  533. +)
  534. +function command_conflicts()
  535. + if program_exists_in_path("egrep") == 0 then
  536. + io.stderr:write("mtn: conflicts: ERROR: require GNU grep command \"egrep\" in PATH\n")
  537. + return
  538. + end
  539. + mtn_automate("get_option", "branch") -- make sure we have a valid workspace
  540. + local rc = execute(
  541. + "egrep",
  542. + "--files-with-matches",
  543. + "--recursive",
  544. + "^(<<<<<<<|=======|>>>>>>>) ",
  545. + "."
  546. + )
  547. +end
  548. +
  549. +-- extra command: "mtn rev[ision] REVISION [ANCESTOR-REVISION]"
  550. +register_command(
  551. + "revision", "REVISION [ANCESTOR-REVISION]",
  552. + "Shows summary information about revision(s)",
  553. + "Shows summary information about a particular revision " ..
  554. + "(or a range of revisions in case an ancestor revision is also specified). " ..
  555. + "This is just a convenience wrapper command around \"mtn log --diffs\".",
  556. + "command_revision"
  557. +)
  558. +alias_command(
  559. + "revision",
  560. + "rev"
  561. +)
  562. +function command_revision(revision, ancestor)
  563. + if revision == nil then
  564. + io.stderr:write("mtn: revision: ERROR: no revision specified\n")
  565. + return
  566. + end
  567. + if ancestor == nil then
  568. + ancestor = revision
  569. + end
  570. + mtn_automate("get_option", "branch") -- make sure we have a valid workspace
  571. + execute("mtn", "log", "--diffs", "--no-graph", "--from", ancestor, "--to", revision)
  572. + if rc ~= 0 then
  573. + io.stderr:write("mtn: revision: ERROR: failed to execute\n")
  574. + end
  575. +end
  576. +
  577. +-- extra command: "mtn base {upgrade|diff}"
  578. +register_command(
  579. + "base", "upgrade|diff",
  580. + "Upgrades or compares current branch against base branch",
  581. + "Upgrade current branch from base branch or compares current " ..
  582. + "branch against base branch. The base branch has to be stored " ..
  583. + "either in the \"mtn:base\" attribute of the root directory " ..
  584. + "or in a \".mtn-base\" file in the root directory.",
  585. + "command_base"
  586. +)
  587. +function command_base(op)
  588. + -- sanity check command line
  589. + if op == nil then
  590. + io.stderr:write("mtn: base: ERROR: no operation specified\n")
  591. + return
  592. + end
  593. + if op ~= "upgrade" and op ~= "diff" then
  594. + io.stderr:write("mtn: base: ERROR: either \"upgrade\" or \"diff\" operation has to be specified\n")
  595. + return
  596. + end
  597. +
  598. + -- determine current branch of workspace
  599. + local branch_this = nil
  600. + local rc, txt = mtn_automate("get_option", "branch")
  601. + if txt ~= nil then
  602. + branch_this = string.match(txt, "^%s*(%S+)%s*$")
  603. + end
  604. + if branch_this == nil then
  605. + io.stderr:write("mtn: base: ERROR: failed to determine current branch\n")
  606. + return
  607. + end
  608. +
  609. + -- determine base branch of workspace
  610. + local branch_base = nil
  611. + local rc, txt = mtn_automate("get_attributes", ".")
  612. + if txt ~= nil then
  613. + branch_base = string.match(txt, "attr%s+\"mtn:base\"%s+\"([^\"]+)\"")
  614. + end
  615. + if branch_base == nil then
  616. + local txt = read_contents_of_file(".mtn-base", "r")
  617. + if txt ~= nil then
  618. + branch_base = string.match(txt, "^%s*(%S+)%s*$")
  619. + end
  620. + end
  621. + if branch_base == nil then
  622. + io.stderr:write("mtn: base: ERROR: failed to determine base branch\n")
  623. + return
  624. + end
  625. +
  626. + -- dispatch according to operation
  627. + if op == "upgrade" then
  628. + -- upgrade current branch by merging in revisions of base branch
  629. + local rc = execute("mtn", "propagate", branch_base, branch_this)
  630. + if rc ~= 0 then
  631. + io.stderr:write("mtn: revision: ERROR: failed to execute \"mtn propagate\"\n")
  632. + return
  633. + end
  634. + rc = execute("mtn", "update")
  635. + if rc ~= 0 then
  636. + io.stderr:write("mtn: revision: ERROR: failed to execute \"mtn update\"\n")
  637. + return
  638. + end
  639. + elseif op == "diff" then
  640. + -- upgrade current branch by merging in revisions of base branch
  641. + local rc = execute("mtn", "diff", "-r", "h:" .. branch_base, "-r", "h:" .. branch_this)
  642. + if rc ~= 0 then
  643. + io.stderr:write("mtn: revision: ERROR: failed to execute \"mtn diff\"\n")
  644. + return
  645. + end
  646. + end
  647. + return
  648. +end
  649. +
  650. +-- #endif
  651. +
  652. Index: work.cc
  653. --- work.cc.orig 2007-12-12 20:45:48 +0100
  654. +++ work.cc 2007-12-13 08:59:14 +0100
  655. @@ -53,28 +53,44 @@
  656. static void
  657. get_revision_path(bookkeeping_path & m_path)
  658. {
  659. +#if defined(RSE) /* alt-book-keeping-root */
  660. + m_path = (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / revision_file_name;
  661. +#else
  662. m_path = bookkeeping_root / revision_file_name;
  663. +#endif
  664. L(FL("revision path is %s") % m_path);
  665. }
  666. static void
  667. get_options_path(bookkeeping_path & o_path)
  668. {
  669. +#if defined(RSE) /* alt-book-keeping-root */
  670. + o_path = (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / options_file_name;
  671. +#else
  672. o_path = bookkeeping_root / options_file_name;
  673. +#endif
  674. L(FL("options path is %s") % o_path);
  675. }
  676. static void
  677. get_options_path(system_path const & workspace, system_path & o_path)
  678. {
  679. +#if defined(RSE) /* alt-book-keeping-root */
  680. + o_path = (directory_exists(workspace / alt_bookkeeping_root_component) ? (workspace / alt_bookkeeping_root_component) : (workspace / bookkeeping_root_component)) / options_file_name;
  681. +#else
  682. o_path = workspace / bookkeeping_root_component / options_file_name;
  683. +#endif
  684. L(FL("options path is %s") % o_path);
  685. }
  686. static void
  687. get_inodeprints_path(bookkeeping_path & ip_path)
  688. {
  689. +#if defined(RSE) /* alt-book-keeping-root */
  690. + ip_path = (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / inodeprints_file_name;
  691. +#else
  692. ip_path = bookkeeping_root / inodeprints_file_name;
  693. +#endif
  694. L(FL("inodeprints path is %s") % ip_path);
  695. }
  696. @@ -205,7 +221,11 @@
  697. void
  698. workspace::get_user_log_path(bookkeeping_path & ul_path)
  699. {
  700. +#if defined(RSE) /* alt-book-keeping-root */
  701. + ul_path = (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / user_log_file_name;
  702. +#else
  703. ul_path = bookkeeping_root / user_log_file_name;
  704. +#endif
  705. L(FL("user log path is %s") % ul_path);
  706. }
  707. @@ -387,7 +407,11 @@
  708. void
  709. workspace::get_local_dump_path(bookkeeping_path & d_path)
  710. {
  711. +#if defined(RSE) /* alt-book-keeping-root */
  712. + d_path = (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / local_dump_file_name;
  713. +#else
  714. d_path = bookkeeping_root / local_dump_file_name;
  715. +#endif
  716. L(FL("local dump path is %s") % d_path);
  717. }
  718. @@ -747,7 +771,11 @@
  719. static inline bookkeeping_path
  720. path_for_detached_nids()
  721. {
  722. +#if defined(RSE) /* alt-book-keeping-root */
  723. + return (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / "detached";
  724. +#else
  725. return bookkeeping_root / "detached";
  726. +#endif
  727. }
  728. static inline bookkeeping_path
  729. @@ -1483,9 +1511,15 @@
  730. N(is_dir_t(new_roster.get_node(new_root)),
  731. F("proposed new root directory '%s' is not a directory") % new_root);
  732. {
  733. +#if defined(RSE) /* alt-book-keeping-root */
  734. + N(!(new_roster.has_node(new_root / bookkeeping_root_component) || new_roster.has_node(new_root / alt_bookkeeping_root_component)),
  735. + F("proposed new root directory '%s' contains illegal path %s or %s")
  736. + % new_root % bookkeeping_root % alt_bookkeeping_root);
  737. +#else
  738. N(!new_roster.has_node(new_root / bookkeeping_root_component),
  739. F("proposed new root directory '%s' contains illegal path %s")
  740. % new_root % bookkeeping_root);
  741. +#endif
  742. }
  743. {
  744. Index: work_migration.cc
  745. --- work_migration.cc.orig 2007-12-12 20:45:48 +0100
  746. +++ work_migration.cc 2007-12-13 08:59:14 +0100
  747. @@ -55,9 +55,18 @@
  748. {
  749. unsigned int format;
  750. bookkeeping_path f_path = bookkeeping_root / "format";
  751. +#if defined(RSE) /* alt-book-keeping-root */
  752. + bookkeeping_path alt_f_path = alt_bookkeeping_root / "format";
  753. + if (!file_exists(f_path) && !file_exists(alt_f_path))
  754. +#else
  755. if (!file_exists(f_path))
  756. +#endif
  757. {
  758. +#if defined(RSE) /* alt-book-keeping-root */
  759. + if (directory_exists(bookkeeping_root) || directory_exists(alt_bookkeeping_root))
  760. +#else
  761. if (directory_exists(bookkeeping_root))
  762. +#endif
  763. format = 1;
  764. else if (directory_exists(file_path() / old_bookkeeping_root_component))
  765. format = 0;
  766. @@ -69,7 +78,11 @@
  767. data f_dat;
  768. try
  769. {
  770. +#if defined(RSE) /* alt-book-keeping-root */
  771. + read_data(file_exists(alt_f_path) ? alt_f_path : f_path, f_dat);
  772. +#else
  773. read_data(f_path, f_dat);
  774. +#endif
  775. format = lexical_cast<unsigned int>(remove_ws(f_dat()));
  776. }
  777. catch (exception & e)
  778. @@ -80,7 +93,11 @@
  779. if (format == 1)
  780. {
  781. W(F("_MTN/format should not exist in a format 1 workspace; corrected"));
  782. +#if defined(RSE) /* alt-book-keeping-root */
  783. + delete_file(file_exists(alt_f_path) ? alt_f_path : f_path);
  784. +#else
  785. delete_file(f_path);
  786. +#endif
  787. }
  788. }
  789. return format;
  790. @@ -90,6 +107,9 @@
  791. workspace::write_ws_format()
  792. {
  793. bookkeeping_path f_path = bookkeeping_root / "format";
  794. +#if defined(RSE) /* alt-book-keeping-root */
  795. + bookkeeping_path alt_f_path = alt_bookkeeping_root / "format";
  796. +#endif
  797. // one or other side of this conditional will always be dead code, but
  798. // both sides should be preserved, to document all historical formats.
  799. // N.B. this will _not_ do the right thing for format 0. Which is fine.
  800. @@ -97,10 +117,19 @@
  801. {
  802. if (file_exists(f_path))
  803. delete_file(f_path);
  804. +#if defined(RSE) /* alt-book-keeping-root */
  805. + if (file_exists(alt_f_path))
  806. + delete_file(alt_f_path);
  807. +#endif
  808. }
  809. else
  810. {
  811. data f_dat(lexical_cast<string>(current_workspace_format) + "\n");
  812. +#if defined(RSE) /* alt-book-keeping-root */
  813. + if (directory_exists(alt_bookkeeping_root))
  814. + write_data(alt_f_path, f_dat);
  815. + else
  816. +#endif
  817. write_data(f_path, f_dat);
  818. }
  819. }
  820. @@ -180,7 +209,11 @@
  821. // information, and _MTN/work does not exist; also, there may be more than
  822. // one parent revision, but we do not have to worry about that here.
  823. +#if defined(RSE) /* alt-book-keeping-root */
  824. + bookkeeping_path rev_path = (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / "revision";
  825. +#else
  826. bookkeeping_path rev_path = bookkeeping_root / "revision";
  827. +#endif
  828. data base_rev_data; MM(base_rev_data);
  829. try
  830. {
  831. @@ -196,7 +229,11 @@
  832. cset workcs;
  833. MM(workcs);
  834. +#if defined(RSE) /* alt-book-keeping-root */
  835. + bookkeeping_path workcs_path = (directory_exists(alt_bookkeeping_root) ? alt_bookkeeping_root : bookkeeping_root) / "work";
  836. +#else
  837. bookkeeping_path workcs_path = bookkeeping_root / "work";
  838. +#endif
  839. bool delete_workcs = false;
  840. if (file_exists(workcs_path))
  841. {