# # add_file "tests/README" # # add_file "tests/t_netsync_largish_file.at" # # add_file "tests/t_rename_dir_add_dir_with_old_name.at" # # patch "AUTHORS" # from [c126b051dbf7eb27b5eeba30a756e079c7f71d3e] # to [d5113319825a1ff4cac54a47f985774b4f5d1b70] # # patch "ChangeLog" # from [41f028c591c054cdc72ebcc3837baa8abc671896] # to [1b2c6d18573b0f351bf3a8c9ac9aaa8da488e9c4] # # patch "Makefile.am" # from [b8121dcf5a8aecc511e437ae64e8bdfbba9e880f] # to [ad9e4d27f5baadaf99c7485aebecc2388b757d9a] # # patch "NEWS" # from [99678784bf033790e0cf616f35a4c016946b6f49] # to [4e6e48c7d84b9e778412486592d47032638dff3f] # # patch "change_set.cc" # from [0f26497e115e7818f164f2c3d9a469c6e784f742] # to [8721281fd257c827409baf2df2ec98e7883e0710] # # patch "constants.cc" # from [444b4e72f8a0f981f059357cf66a8b08c05ed734] # to [cc76e26e5126f2a43b1a91c0ce1213a77861d34c] # # patch "contrib/monotone.bash_completion" # from [f947568a0d2f341c8a95956f5f84ab250dff4a68] # to [796f8dc91d99045363cb95c381fe39f27bf27b5f] # # patch "contrib/monotone.el" # from [d73d2eedf89044fa347a8de9bdf2c9717d2cb151] # to [e40a9009178b2ca63eff28d78efe9722ce40f696] # # patch "database_check.cc" # from [1098ea2b6e2a53449fd89dd6ae815f42d4206cd4] # to [924b949941d72064a292451e72c28bfb2e80755c] # # patch "diff_patch.cc" # from [e798174667fdbb10359025f4b050b0b1c017705c] # to [c080a1bd6428d24243c0fc224414be6eb0fb7949] # # patch "monotone.texi" # from [13bed7469b4e155326caade82d7328129accdbec] # to [17687a1f93e1694cb6433d5e878ce3a00c08cd7f] # # patch "netsync.cc" # from [04871c9d35e04f3f8ed0d10c6311c643c5f79df1] # to [98bb94f9c22a40bc6f826cad62737a7f9bfb9a04] # # patch "smap.hh" # from [bf2f49a88508bb21de8bc201c02e3050835a6d95] # to [d4acf13bff4208cfe2d87cb93fcb182a290d77f8] # # patch "std_hooks.lua" # from [cd6f8109837ec89d642901697933e23dd44faf1d] # to [a09034cf15e000407c7fdbea620de03f79f8a73e] # # patch "tests/README" # from [] # to [fdbb3d9f63642092343e0ea58b7ee937f910103a] # # patch "tests/t_database_check.at" # from [11b64267ef57980019f461ea1acca582d2cb989e] # to [3ea731d55685488c6dadb5580b4cd04dc130e855] # # patch "tests/t_diff_binary.at" # from [651f781bf58848169446baee444f3f1418b7b24f] # to [de45d9dca34e5765bd998968752d25368c8238e1] # # patch "tests/t_netsync_largish_file.at" # from [] # to [0b5e0097e6e6e776b27d24fbe112ca786f27a455] # # patch "tests/t_rename_dir_add_dir_with_old_name.at" # from [] # to [b005c1839d019fa629d02fa1373f391715937594] # # patch "tests/t_vcheck.at" # from [247f296fb06b33fb2609231c983517384b50a437] # to [8656291fbb8e643e82f3bfb8ffa5616346388cb6] # # patch "testsuite.at" # from [03503ada6caff92de4120e9248a98cfacf60862d] # to [fde2283ff36e562055f019ac389b61299d2af057] # # patch "ui.cc" # from [82a7a36a452c7d6fa3b7f042189d8901f514b189] # to [bf5397526968d5189f12fef56ecd4990f622beef] # # patch "win32/process.cc" # from [080e7529f15e54f058f117b6c57d822257ebd48b] # to [f20f385828115ec65d4565e80d58822335c80bc2] # # patch "win32/terminal.cc" # from [956b84cf7bf5fb26788e77b380935d00291f060e] # to [f747b2f947980bbf6561cd97441709b82159cf29] # --- AUTHORS +++ AUTHORS @@ -46,12 +46,13 @@ Christian Kollee Faheem Mitha Neil Conway - Wojciech Miłkowski + Wojciech Miłkowski Georg-W. Koltermann Daniel Berlin Jon Bright Corey Halpin Jeremy Cowgar + Martin Dvorak supporting files: --- ChangeLog +++ ChangeLog @@ -1,5 +1,112 @@ +2005-04-16 Sebastian Spaeth + + * add tests/README on how to create/run tests + +2005-04-16 Nathaniel Smith + + * tests/t_rename_dir_add_dir_with_old_name.at: XFAIL. + +2005-04-16 Nathaniel Smith + + * tests/t_diff_binary.at: Un-XFAIL. + +2005-04-16 Nathaniel Smith + + * monotone.texi (Network Service): Rewrite to include former + Exchanging Keys section. + (Branching and Merging): New tutorial section, inspired by a patch + from Martin Kihlgren . + (CVS Phrasebook): Add "Importing a New Project". + + * AUTHORS: Add Martin Dvorak. + +2005-04-15 Martin Dvorak + + * tests/t_rename_dir_add_dir_with_old_name.at: New test. + * testsuite.at: Add it. + +2005-04-16 Matt Johnston + + * change_set.cc (compose_rearrangement): remove logging statements + that were using noticable CPU time. + +2005-04-15 Olivier Andrieu + + * diff_patch.cc(guess_binary): do not use '\x00' as first + character of a C string ... + +2005-04-15 Sebastian Spaeth + + * ui.cc: print byte progress to one decimal place + in k or M. + * netsync.cc: update dot ticker every 1024 bytes. + +2005-04-15 Matt Johnston + + * change_set.cc (confirm_proper_tree): use bitsets rather than maps + for tracking set membership. + * smap.hh: return reverse iterators properly, iterate over the vector + rather than self in ensure_sort() + +2005-04-14 Derek Scherger + + * database_check.cc (check_db): fail with N(...) when problems are + detected to exit with a non-zero status + +2005-04-14 Derek Scherger + + * monotone.texi (Informative): update description of 'diff' with + two revision arguments + +2005-04-14 Matthew Gregan + + * win32/process.cc: Fix build on MingW 3.2.0-rc[123] by adding + include. + +2005-04-14 Jon Bright + * win32/process.cc (process_spawn): Add some extra debug info + * std_hooks.lua (execute): If pid is -1, don't try and wait on + the process + +2005-04-14 Matt Johnston + + * change_set.cc (confirm_unique_entries_in_directories): use a + std::vector rather than std::map for better performance (only sort + once). + * smap.hh: an invariant + +2005-04-14 Nathaniel Smith + + * tests/t_vcheck.at: Update notes. + +2005-04-14 Jeremy Cowgar + + * monotone.texi (Making Changes): Fixed duplicate paragraph + * NEWS: Corrected spelling error in my name. + 2005-04-13 Nathaniel Smith + * monotone.texi (Informative): 'diff' with two revision arguments + can now be filtered by file. + + * constants.cc (netcmd_payload_limit): Bump to 256 megs. + +2005-04-14 Olivier Andrieu + + * Makefile.am: silence cmp + +2005-04-14 Matthew Gregan + + * win32/terminal.cc (have_smart_terminal): Implement for Win32. + +2005-04-13 Matthew Gregan + + * tests/t_netsync_largish_file.at: Add test for netsyncing largish + (32MB) files. This test is failing at present. + * testsuite.at: Add new test. + +2005-04-13 Nathaniel Smith + * tests/t_setup_checkout_modify_new_dir.at: * tests/t_update_off_branch.at: New tests. * testsuite.at: Add them. @@ -7,6 +114,8 @@ * commands.cc (checkout): Tweak branch checking logic. (update): Make user explicitly switch branches. +####### Ancestor +======= end 2005-04-13 Nathaniel Smith * rcs_import.cc (import_cvs_repo): Check that user isn't trying to @@ -2686,7 +2795,7 @@ * AUTHORS: Mention Wojciech and Neil. * revision.cc (calculate_ancestors_from_graph): Make non-recursive. -2005-01-17 Wojciech MiÃ…Â‚kowski +2005-01-17 Wojciech Miłkowski * std_hooks.lua: Teach about meld. --- Makefile.am +++ Makefile.am @@ -338,12 +338,12 @@ %.h: %.sql txt2c Makefile ./txt2c $< $(*F) >address@hidden - cmp address@hidden $@ || mv address@hidden $@ + cmp -s address@hidden $@ || mv address@hidden $@ rm -f address@hidden %.h: %.lua txt2c Makefile ./txt2c $< $(*F) >address@hidden - cmp address@hidden $@ || mv address@hidden $@ + cmp -s address@hidden $@ || mv address@hidden $@ rm -f address@hidden # A fake target so we can use MT/revision as a prerequisite, yet not @@ -355,7 +355,7 @@ if [ ! -f $@ ]; then echo "unknown" > $@; fi package_revision.c: package_revision.txt txt2c Makefile ./txt2c --strip-trailing --no-static $< package_revision >address@hidden - cmp address@hidden $@ || mv address@hidden $@ + cmp -s address@hidden $@ || mv address@hidden $@ rm -f address@hidden .PHONY: package_full_revision.txt apidocs @@ -372,7 +372,7 @@ echo ' further changes may have been made.') >> $@ package_full_revision.c: package_full_revision.txt txt2c Makefile ./txt2c --no-static $< package_full_revision >address@hidden - cmp address@hidden $@ || mv address@hidden $@ + cmp -s address@hidden $@ || mv address@hidden $@ rm -f address@hidden # automake doesn't build html docs --- NEWS +++ NEWS @@ -41,7 +41,7 @@ - New "--depth" argument to 'log'. Thanks to Richard Levitte . - 'db info' gives statistics on space usage. - - new command 'dropkey'. Thanks to Jeremey Cowgar + - new command 'dropkey'. Thanks to Jeremy Cowgar . - robustness improvement: if monotone crashes in a working directory and --dump and --debug were not specified, saves --- change_set.cc +++ change_set.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include "basic_io.hh" #include "change_set.hh" @@ -513,19 +514,30 @@ static void confirm_proper_tree(path_state const & ps) { - std::map confirmed; - I(ps.find(root_tid) == ps.end()); + if (ps.empty()) + return; + + I(ps.find(root_tid) == ps.end()); // Note that this find() also ensures + // sortedness of ps. + + tid min_tid = ps.begin()->first; + tid max_tid = ps.rbegin()->first; + size_t tid_range = max_tid - min_tid + 1; + + boost::dynamic_bitset<> confirmed(tid_range); + boost::dynamic_bitset<> ancs(tid_range); + for (path_state::const_iterator i = ps.begin(); i != ps.end(); ++i) { tid curr = i->first; path_item item = i->second; - std::map ancs; + ancs.reset(); - while (confirmed.find(curr) == confirmed.end()) + while (confirmed.test(curr - min_tid) == false) { sanity_check_path_item(item); - I(ancs.find(curr) == ancs.end()); - ancs.insert(std::make_pair(curr,true)); + I(ancs.test(curr - min_tid) == false); + ancs.set(curr - min_tid); if (path_item_parent(item) == root_tid) break; else @@ -542,16 +554,14 @@ I(path_item_type(item) == ptype_directory); } } - std::copy(ancs.begin(), ancs.end(), - inserter(confirmed, confirmed.begin())); + confirmed |= ancs; } - I(confirmed.find(root_tid) == confirmed.end()); } static void confirm_unique_entries_in_directories(path_state const & ps) -{ - std::map, bool> entries; +{ + std::vector > entries; for (path_state::const_iterator i = ps.begin(); i != ps.end(); ++i) { if (null_name(path_item_name(i->second))) @@ -562,9 +572,27 @@ std::pair p = std::make_pair(path_item_parent(i->second), path_item_name(i->second)); - I(entries.find(p) == entries.end()); - entries.insert(std::make_pair(p,true)); + entries.push_back(p); } + + // Now we check that entries is unique + if (entries.empty()) + return; + + std::sort(entries.begin(), entries.end()); + + std::vector >::const_iterator leader, lagged; + leader = entries.begin(); + lagged = entries.begin(); + + I(leader != entries.end()); + ++leader; + while (leader != entries.end()) + { + I(*leader != *lagged); + ++leader; + ++lagged; + } } static void @@ -733,15 +761,19 @@ if (old_path == new_path) { + /* L(F("skipping preserved %s %d : '%s'\n") % (path_item_type(old_item) == ptype_directory ? "directory" : "file") % curr % old_path); + */ continue; } + /* L(F("analyzing %s %d : '%s' -> '%s'\n") % (path_item_type(old_item) == ptype_directory ? "directory" : "file") % curr % old_path % new_path); + */ if (null_name(path_item_name(old_item))) { --- constants.cc +++ constants.cc @@ -148,7 +148,9 @@ + 1 // smallest uleb possible + 4); // adler32 - size_t const netcmd_payload_limit = 0xffffff; + // allow payloads up to 256 megs (this sets the in-practice maximum size of + // a compressed file/manifest). + size_t const netcmd_payload_limit = 2 << 27; size_t const netcmd_maxsz = netcmd_minsz + netcmd_payload_limit; size_t const netcmd_minimum_bytes_to_bother_with_gzip = 0xfff; --- contrib/monotone.bash_completion +++ contrib/monotone.bash_completion @@ -43,9 +43,7 @@ } _monotone() { - local cur=${COMP_WORDS[COMP_CWORD]} - local prev=${COMP_WORDS[COMP_CWORD-1]} - local mono_db + local cur prev mono_db for w in address@hidden ; do if [[ "$w" == --db=* ]] ; then @@ -55,12 +53,16 @@ if [ -z "$mono_db" ] ; then for i in address@hidden ; do [ $i -eq 0 ] && continue - if [ "${COMP_WORDS[$i-1]}" == --db ] ; then + prev="${COMP_WORDS[$i-1]}" + if [ $prev == --db -o $prev == -d ] ; then mono_db="--db=${COMP_WORDS[$i]}" ; break fi done fi + cur=${COMP_WORDS[COMP_CWORD]} + prev=${COMP_WORDS[COMP_CWORD-1]} + case $cur in --db=* | --rcfile=* | --dump=* ) cur="${cur#*=}" --- contrib/monotone.el +++ contrib/monotone.el @@ -1,13 +1,17 @@ ;;; monotone.el --- Run monotone from within Emacs. ;; Copyright 2005 by Olivier Andrieu +;; Version 0.2 2005-04-13 ;; This defines `monotone-diff', `monotone-status', `monotone-add', -;; `monotone-drop', `monotone-revert' and `monotone-commit'. They call -;; monotone on the current file. With a prefix argument (C-u) the -;; command is applied on the whole tree. +;; `monotone-drop', `monotone-revert' and `monotone-commit'. These +;; functions call the corresponding monotone command, restricted to +;; the current file. With a prefix argument (C-u) the command is +;; applied unrestricted (on the whole tree). As an exception, +;; `monotone-status' has the opposite behaviour: it is unrestricted by +;; default, restricted with a prefix argument. ;; /!\ beware of bugs: `monotone-commit' is more dangerous than the -;; other two as it modifies the database. +;; others since it writes to the database. (defvar monotone-program @@ -24,20 +28,21 @@ (append other-args (list arg)) other-args)) -(defun monotone-run (command &optional arg) - (unless buffer-file-name - (error "This buffer is not associated with a file")) - (let ((file - (if arg - nil - (file-name-nondirectory buffer-file-name))) - (dir (file-name-directory buffer-file-name))) +(defun monotone-run (command &optional global) + (let (monotone-arg + (dir default-directory)) + (unless global + (setq monotone-arg + (if buffer-file-name + (file-name-nondirectory buffer-file-name) + "."))) + (pop-to-buffer monotone-buffer) (setq buffer-read-only nil) (erase-buffer) (cd dir) (apply 'call-process monotone-program nil t nil - (may-append file command)) + (may-append monotone-arg command)) (goto-char (point-min)) (fundamental-mode) (setq buffer-read-only t) @@ -54,11 +59,11 @@ (diff-mode))) (defun monotone-status (arg) - "Run `monotone status' on the current buffer's file. When called with -a prefix argument, do it for the whole tree." + "Run `monotone status'. When called with a prefix argument, do it +for the current buffer's file only." (interactive "P") (save-selected-window - (monotone-run "status" arg))) + (monotone-run "status" (not arg)))) (defun monotone-add () "Run `monotone add' on the current buffer's file." @@ -75,12 +80,12 @@ (defun monotone-revert () "Run `monotone revert' on the current buffer's file." (interactive) - (if (and buffer-file-name - (yes-or-no-p - (format "Are you sure you want monotone to revert '%s' ? " buffer-file-name))) - (save-selected-window - (monotone-run "revert") - (revert-buffer t t)))) + (when (yes-or-no-p + (format "Are you sure you want monotone to revert '%s' ? " + (or buffer-file-name default-directory))) + (save-selected-window + (monotone-run "revert")) + (revert-buffer t t))) (defun monotone-install-keymap () (unless monotone-map @@ -122,36 +127,32 @@ "Run `monotone commit' on the current buffer's file. When called with a prefix argument, do it on the whole tree." (interactive "P") - (if (null buffer-file-name) - (error "This buffer is not associated with a file")) - (let ((file - (if arg - nil - (file-name-nondirectory buffer-file-name))) - (dir (file-name-directory buffer-file-name))) + (setq monotone-commit-arg + (cond (arg nil) + (buffer-file-name (file-name-nondirectory buffer-file-name)) + (t ".")) + monotone-commit-dir default-directory) + (pop-to-buffer "*monotone ChangeLog*") + (setq buffer-read-only nil) + (erase-buffer) + (cd monotone-commit-dir) + (apply 'call-process monotone-program nil t nil + (may-append monotone-commit-arg "status")) + (goto-char (point-min)) + (while (progn + (insert "MT: ") + (= 0 (forward-line 1)))) + (goto-char (point-min)) + (dolist + (l '("" + "MT: ----------------------------------------------------------------------" + "MT: Enter Log. Lines beginning with `MT:' are removed automatically." + "MT: Type C-c C-c to commit, kill the buffer to abort.")) + (insert l "\n")) + (goto-char (point-max)) + (insert "----------------------------------------------------------------------\n") + (text-mode) + (monotone-install-keymap) + (goto-char (point-min)) + (shrink-window-if-larger-than-buffer)) - (pop-to-buffer "*monotone ChangeLog*") - (setq monotone-commit-arg file - monotone-commit-dir dir) - (setq buffer-read-only nil) - (erase-buffer) - (cd dir) - (apply 'call-process monotone-program nil t nil - (may-append file "status")) - (goto-char (point-min)) - (while (progn - (insert "MT: ") - (= 0 (forward-line 1)))) - (goto-char (point-min)) - (dolist - (l '("" - "MT: ----------------------------------------------------------------------" - "MT: Enter Log. Lines beginning with `MT:' are removed automatically." - "MT: Type C-c C-c to commit, kill the buffer to abort.")) - (insert l "\n")) - (goto-char (point-max)) - (insert "----------------------------------------------------------------------\n") - (text-mode) - (monotone-install-keymap) - (goto-char (point-min)) - (shrink-window-if-larger-than-buffer))) --- database_check.cc +++ database_check.cc @@ -671,7 +671,8 @@ missing_keys; if (total > 0) - P(F("check complete: %d files; %d manifests; %d revisions; %d keys; %d certs; %d problems detected\n") + N(total == 0, + F("check complete: %d files; %d manifests; %d revisions; %d keys; %d certs; %d problems detected\n") % checked_files.size() % checked_manifests.size() % checked_revisions.size() --- diff_patch.cc +++ diff_patch.cc @@ -25,7 +25,8 @@ { // these do not occur in ASCII text files // FIXME: this heuristic is (a) crap and (b) hardcoded. fix both these. - if (s.find_first_of("\x00\x01\x02\x03\x04\x05\x06\x0e\x0f" + if (s.find_first_of('\x00') != string::npos || + s.find_first_of("\x01\x02\x03\x04\x05\x06\x0e\x0f" "\x10\x11\x12\x13\x14\x15\x16\x17\x18" "\x19\x1a\x1c\x1d\x1e\x1f") != string::npos) return true; --- monotone.texi +++ monotone.texi @@ -212,11 +212,11 @@ @end ifnotinfo Version control systems, such as monotone, are principally concerned -with the storage and management of @i{multiple} versions of some -files. One way to store multiple versions of a file is, literally, to -save a separate @i{complete} copy of the file, every time you make a +with the storage and management of @i{multiple} versions of some files. +One way to store multiple versions of a file is, literally, to save a +separate @i{complete} copy of the file, every time you make a change. When necessary, monotone will save complete copies of your -files in their, compressed with the @command{zlib} compression format. +files, compressed with the @command{zlib} compression format. @ifinfo @smallexample @@ -1071,13 +1071,13 @@ @menu * Creating a Database:: * Generating Keys:: -* Exchanging Keys:: * Starting a New Project:: * Adding Files:: * Committing Work:: * Network Service:: * Making Changes:: * Dealing with a Fork:: +* Branching and Merging:: @end menu @@ -1221,82 +1221,10 @@ Abe and Beth do the same, with their secret passphrases. @page address@hidden Exchanging Keys address@hidden Exchanging Keys - -Jim, Abe and Beth all wish to work with one another, and trust one -another. For monotone to accept this situation, the team members will -need to exchange the public parts of their @sc{rsa} key with each -other. - -First, Jim exports his public key: - address@hidden address@hidden -$ monotone --db=~/jim.db pubkey jim@@juicebot.co.jp >~/jim.pubkey address@hidden group address@hidden smallexample - -His public key is just a plain block of ASCII text: - address@hidden address@hidden -$ cat ~/jim.pubkey -[pubkey jim@@juicebot.co.jp] -MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCbaVff9SF78FiB/1nUdmjbU/TtPyQqe/fW -CDg7hSg1yY/hWgClXE9FI0bHtjPMIx1kBOig09AkCT7tBXM9z6iGWxTBhSR7D/qsJQGPorOD -DO7xovIHthMbZZ9FnvyB/BCyiibdWgGT0Gtq94OKdvCRNuT59e5v9L4pBkvajb+IzQIBEQ== -[end] address@hidden group address@hidden smallexample - -Abe also exports his public key: - address@hidden address@hidden -$ monotone --db=~/abe.db pubkey abe@@juicebot.co.jp >~/abe.pubkey address@hidden group address@hidden smallexample - -As does Beth: - address@hidden address@hidden -$ monotone --db=~/beth.db pubkey beth@@juicebot.co.jp >~/beth.pubkey address@hidden group address@hidden smallexample - -Then all three team members exchange keys. The keys are not secret, -but the team members must be relatively certain that they are -communicating with the person they intend to trust, when exchanging -keys, and not some malicious person pretending to be a team -member. Key exchange may involve sending keys over an encrypted -medium, or meeting in person to exchange physical copies, or any -number of techniques. All that matters, ultimately, is for each team -member to receive the keys of the others. - -So eventually, after key exchange, Jim has Beth's and Abe's public key -files in his home directory, along with his own. He tells monotone to -read the associated key packets into his database: - address@hidden address@hidden -$ monotone --db=~/jim.db read <~/abe.pubkey -monotone: read 1 packet -$ monotone --db=~/jim.db read <~/beth.pubkey -monotone: read 1 packet address@hidden group address@hidden smallexample - -Beth and Abe similarly tell monotone to read read the two new public -keys they received into their respective databases. - - address@hidden @node Starting a New Project @section Starting a New Project -Before they can begin work on the project, Jim needs to create a +Before he can begin work on the project, Jim needs to create a @i{working copy} --- a directory whose contents monotone will keep track of. Often, one works on projects that someone else has started, and creates working copies with the @code{checkout} command, which you'll @@ -1529,10 +1457,7 @@ @smallexample @group $ monotone --db=jim.db --branch=jp.co.juicebot.jb7 commit --message='initial checkin of project' -monotone: beginning commit -monotone: manifest 2098eddbe833046174de28172a813150a6cbda7b -monotone: revision 2e24d49a48adf9acf3a1b6391a080008cbef9c21 -monotone: branch jp.co.juicebot.jb7 +monotone: beginning commit on branch 'jp.co.juicebot.jb7' monotone: committed revision 2e24d49a48adf9acf3a1b6391a080008cbef9c21 @end group @end smallexample @@ -1643,12 +1568,68 @@ @section Network Service Jim now decides he will make his base revision available to his -employees. To do this first adds a small amount of extra information -to his @file{.monotonerc} file, permitting Abe and Beth to access his -database: +employees. To do this he gives Abe and Beth permission to access his +database. There are two parts to this: first, he has to get a copy of +each of their public keys; then, he has to tell monotone that the +holders of those keys are permitted to access his database. +First, Abe exports his public key: + @smallexample @group +$ monotone --db=~/abe.db pubkey abe@@juicebot.co.jp >~/abe.pubkey address@hidden group address@hidden smallexample + +His public key is just a plain block of ASCII text: + address@hidden address@hidden +$ cat ~/abe.pubkey +[pubkey abe@@juicebot.co.jp] +MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCbaVff9SF78FiB/1nUdmjbU/TtPyQqe/fW +CDg7hSg1yY/hWgClXE9FI0bHtjPMIx1kBOig09AkCT7tBXM9z6iGWxTBhSR7D/qsJQGPorOD +DO7xovIHthMbZZ9FnvyB/BCyiibdWgGT0Gtq94OKdvCRNuT59e5v9L4pBkvajb+IzQIBEQ== +[end] address@hidden group address@hidden smallexample + +Beth also exports her public key: + address@hidden address@hidden +$ monotone --db=~/beth.db pubkey beth@@juicebot.co.jp >~/beth.pubkey address@hidden group address@hidden smallexample + +Then Abe and Beth both send their keys to Jim. The keys are not secret, +but the team members must be relatively certain that they are +communicating with the person they intend to trust, when exchanging +keys, and not some malicious person pretending to be a team +member. Key exchange may involve sending keys over an encrypted +medium, or meeting in person to exchange physical copies, or any +number of techniques. All that matters, ultimately, is that Jim receive +both Abe and Beth's key. + +So eventually, after key exchange, Jim has the public key files in his +home directory. He tells monotone to read the associated key packets +into his database: + address@hidden address@hidden +$ monotone --db=~/jim.db read <~/abe.pubkey +monotone: read 1 packet +$ monotone --db=~/jim.db read <~/beth.pubkey +monotone: read 1 packet address@hidden group address@hidden smallexample + +Now Jim's monotone is able to identify Beth and Abe, and he is ready to +give them permission to access his database. He does this by adding a +small amount of extra information to his @file{.monotonerc} file: + address@hidden address@hidden $ cat >>~/.monotonerc function get_netsync_read_permitted (collection, identity) if (identity == "abe@@juicebot.co.jp") then return true end @@ -1719,8 +1700,9 @@ always running; this way, everyone always knows where to go to get the latest changes, and people can push their changes out without first calling their friends and making sure that they have their servers -running. To support this style of working, monotone remembers the first -server you use, and makes that the default for future operations. +running. To make this style of working more convenient, monotone +remembers the first server you use, and makes that the default for +future operations. @page @node Making Changes @@ -1785,10 +1767,8 @@ @smallexample @group $ monotone commit -monotone: beginning commit -monotone: manifest b33cb337dccf21d6673f462d677a6010b60699d1 -monotone: revision 70decb4b31a8227a629c0e364495286c5c75f979 -monotone: branch jp.co.juicebot.jb7 +monotone: beginning commit on branch 'jp.co.juicebot.jb7' +monotone: commited revision 70decb4b31a8227a629c0e364495286c5c75f979 @end group @end smallexample @@ -1886,16 +1866,6 @@ @end group @end smallexample -and logs her changes in @file{MT/log} right away so she does not -forget what she has done: - address@hidden address@hidden -$ vi MT/log -* src/banana.c: Added polling implementation address@hidden group address@hidden smallexample - Later, she commits her work. Monotone again invokes an external editor for her to edit her log message, but this time it fills in the messages she's written so far, and she simply checks them over one last time @@ -1904,10 +1874,7 @@ @smallexample @group $ monotone commit -monotone: beginning commit -monotone: manifest eaebc3c558d9e30db6616ef543595a5a64cc6d5f -monotone: revision 80ef9c9d251d39074d37e72abf4897e0bbae1cfb -monotone: branch jp.co.juicebot.jb7 +monotone: beginning commit on branch 'jp.co.juicebot.jb7' monotone: committed revision 80ef9c9d251d39074d37e72abf4897e0bbae1cfb @end group @end smallexample @@ -2022,10 +1989,7 @@ @smallexample @group $ monotone commit --message='interrupt implementation of src/banana.c' -monotone: beginning commit -monotone: manifest de81e46acb24b2950effb18572d5166f83af3881 -monotone: revision 8b41b5399a564494993063287a737d26ede3dee4 -monotone: branch jp.co.juicebot.jb7 +monotone: beginning commit on branch 'jp.co.juicebot.jb7' monotone: committed revision 8b41b5399a564494993063287a737d26ede3dee4 @end group @end smallexample @@ -2136,6 +2100,95 @@ step) and your committed state is still safe. It is therefore recommended that you commit your work @emph{first}, before merging. address@hidden address@hidden Branching and Merging address@hidden Branching and Merging + +So by now you're familiar with making changes, sharing them with other +people, and integrating your changes with their changes. Sometimes, +though, you may want to make some changes, and @emph{not} integrate them +with other people's --- or at least not right away. One way to do this +would be to simply never run @command{monotone merge}; but it would +quickly become confusing to try and keep track of which changes were in +which revisions. This is where @emph{branches} are useful. + +Continuing our example, suppose that Jim is so impressed by Beth's work +on banana juice support that he assigns her to work on the JuiceBot 7's +surprise new feature: muffins. In the mean time, Abe will continue +working on the JuiceBot's basic juice-related function. + +The changes required to support muffins are somewhat complicated, and +Beth is worried that her work might destabilize the program, and +interfere with Abe's work. In fact, she isn't even sure her first +attempt will turn out to be the right approach; she might work on it for +a while and then decide it was a bad idea, and should be discarded. For +all these reasons, she decides that she will work on a branch, and then +once she is satisfied with the new code, she will merge back onto the +mainline. + +She decides that since main development is in branch address@hidden, she will use branch address@hidden So, she makes the first few edits to +the new muffins code, and commits it on a new branch by simply passing address@hidden to commit: + address@hidden address@hidden +$ monotone commit --branch=jp.co.juicebot.jb7.muffins --message='initial autobake framework' +monotone: beginning commit on branch 'jp.co.juicebot.jb7.muffins' +monotone: committed revision d33caefd61823ecbb605c39ffb84705dec449857 address@hidden group address@hidden smallexample + +That's all there is to it --- now there is a address@hidden branch, with her initial checkin on +it. She can make further checkins from the same working copy, and they +will automatically go to the muffins branch; if anyone else wants to +help her work on muffins, they can check out that branch as usual. + +Of course, while Beth is working on the new muffins code, Abe is still +making fixes to the main line. Occasionally, Beth wants to integrate +his latest work into the muffins branch, so that her version doesn't +fall too far behind. She does this by using the @command{propagate} +command: + address@hidden address@hidden +$ monotone propagate jp.co.juicebot.jb7 jp.co.juicebot.jb7.muffins +monotone: propagating jp.co.juicebot.jb7 -> jp.co.juicebot.jb7.muffins +monotone: [source] da003f115752ac6e4750b89aaca9dbba178ac80c +monotone: [target] d0e5c93bb61e5fd25a0dadf41426f209b73f40af +monotone: common ancestor 853b8c7ac5689181d4b958504adfb5d07fd959ab found address@hidden group address@hidden smallexample + +The @command{propagate} merges all of the new changes on one branch onto +another. + +When the muffins code is eventually stable and ready to be integrated +into the main line of development, she simple propagates the other way: + address@hidden address@hidden +$ monotone propagate jp.co.juicebot.jb7.muffins jp.co.juicebot.jb7 +monotone: propagating jp.co.juicebot.jb7 -> jp.co.juicebot.jb7.muffins +monotone: [source] 4e48e2c9a3d2ca8a708cb0cc545700544efb5021 +monotone: [target] bd29b2bfd07644ab370f50e0d68f26dcfd3bb4af +monotone: common ancestor 652b1035343281a0d2a5de79919f9a31a30c9028 found address@hidden group address@hidden smallexample + +Monotone always records the full history of all merges, and is designed +to handle an arbitrarily complicated graph of changes. You can make a +branch, then branch off from that branch, propagate changes between +arbitrary branches, and so on; monotone will track all of it, and do +something sensible for each merge. Of course, it is still probably a +good idea to come up with some organization of branches and a plan for +which should be merged to which other ones. Monotone may keep track of +graphs of arbitrary complexity; but, you will have more trouble. +Whatever arrangement of branches you come up with, though, monotone +should be able to handle it. + @node Advanced Uses @chapter Advanced Uses @@ -2952,7 +3005,7 @@ @tab @smallexample @group -$ monotone diff 3e7db 278df +$ monotone diff -r 3e7db -r 278df @end group @end smallexample @end multitable @@ -3034,6 +3087,29 @@ manifest of the current revision. address@hidden Importing a New Project + address@hidden @columnfractions .4 .4 address@hidden address@hidden address@hidden +$ cvs import wobbler vendor start address@hidden group address@hidden smallexample address@hidden address@hidden address@hidden +$ monotone --db=/path/to/database.db --branch=com.foo.wobbler setup . +$ monotone add . +$ monotone commit address@hidden group address@hidden smallexample address@hidden multitable + +The @command{setup} command turns an ordinary directory into a +monotone working copy. After that, you can add your files and commit +them as usual. + @heading Initializing a Repository @multitable @columnfractions .4 .4 @@ -3525,6 +3601,7 @@ @itemx monotone diff address@hidden @itemx monotone diff address@hidden @var{pathname...} @itemx monotone diff address@hidden address@hidden address@hidden monotone diff address@hidden address@hidden @var{pathname...} These commands print out GNU ``unified diff format'' textual difference listings between various manifest versions. With no @option{--revision} @@ -3535,9 +3612,7 @@ differences between the revision @var{id} and the current revision in the working copy. With two @option{--revision} options @command{diff} will print the differences between revisions @var{id1} and @var{id2}, -ignoring any working copy. Note that no @var{pathname...} arguments may -be specified to restrict the diff output in this case. Restrictions may -only be applied to the current, in-progress, working copy revision. +ignoring any working copy. In all cases, monotone will print a textual summary -- identical to the summary presented by @command{monotone status} -- of the logical @@ -3546,8 +3621,8 @@ a program processing the diff, such as @command{patch}. Specifying pathnames to the @command{diff} command restricts the set of -changes that are visible and results in only a partial diff of the -working copy. Changes to files not included in the specified set of +changes that are visible and results in only a partial diff between +two revisions. Changes to files not included in the specified set of pathnames will be ignored. From within a subdirectory of the working copy the @command{diff} --- netsync.cc +++ netsync.cc @@ -2897,8 +2897,8 @@ session sess(role, client_voice, collections, all_collections, app, address(), server.get_socketfd(), timeout); - sess.byte_in_ticker.reset(new ticker("bytes in", ">", 256, true)); - sess.byte_out_ticker.reset(new ticker("bytes out", "<", 256, true)); + sess.byte_in_ticker.reset(new ticker("bytes in", ">", 1024, true)); + sess.byte_out_ticker.reset(new ticker("bytes out", "<", 1024, true)); if (role == sink_role) { sess.cert_in_ticker.reset(new ticker("certs in", "c", 3)); --- smap.hh +++ smap.hh @@ -86,10 +86,11 @@ std::sort(vec.begin(), vec.end(), val_cmp); // make sure we don't have any duplicate entries const_iterator leader, lagged; - lagged = begin(); - leader = begin(); + lagged = vec.begin(); + leader = vec.begin(); + I(leader != vec.end()); ++leader; - for (; leader != end(); ++lagged, ++leader) + for (; leader != vec.end(); ++lagged, ++leader) I(lagged->first != leader->first); damaged = false; } @@ -164,13 +165,13 @@ iterator begin() { return vec.begin(); } iterator end() { return vec.end(); } - iterator rbegin() { return vec.rbegin(); } - iterator rend() { return vec.rend(); } + reverse_iterator rbegin() { return vec.rbegin(); } + reverse_iterator rend() { return vec.rend(); } const_iterator begin() const { return vec.begin(); } const_iterator end() const { return vec.end(); } - const_iterator rbegin() const { return vec.rbegin(); } - const_iterator rend() const { return vec.rend(); } + const_reverse_iterator rbegin() const { return vec.rbegin(); } + const_reverse_iterator rend() const { return vec.rend(); } bool empty() const { return vec.empty(); } size_type size() const { return vec.size(); } --- std_hooks.lua +++ std_hooks.lua @@ -15,7 +15,7 @@ local pid local ret = -1 pid = spawn(path, unpack(arg)) - ret, pid = wait(pid) + if (pid ~= -1) then ret, pid = wait(pid) end return ret end --- tests/README +++ tests/README @@ -0,0 +1,48 @@ +HOWTO make tests +================ + +Quick and dirty howto, to get you up to create and run tests. +Very early draft. Feel free to improve. + +Running tests: +-------------- +- Starting in the monotone main dir. After having './configure'd monotone you + can do 'make testsuite' to create 'testsuite'. Running './testsuite' will + run all tests. +- 'testsuite -l' lists the names and numbers of all available tests +- 'testsuite ' runs only test number n +- option -v will show the command outputs +- option -d will keep the testsuite.dir files for post-test debugging +- option -h is your friend :) + +Creating tests: +--------------- +- Copy and paste is your friend :) +- TODO: need more here... + + +Template for a test (name t_.at +------------------- + +AT_SETUP([brief test description goes here]) +MONOTONE_SETUP + +#the next lines (including AT_XFAIL_IF) state that the test is +#expected to fail as this is still a bug. Remove if it should pass! +# This test is a bug report. It is expected to fail +AT_XFAIL_IF(true) + +#AT_CHECK executes a shell command, second argument is the error +#return code we expect, third argument is the output we expect from +#stdout. use ignore if you don't care about the output. If oyu use +#stdout all following commands can use file 'stdout' for further +#processing. Same goes with 'stderr' as the last argument +#see autoconf tutorials +#e.g. http://www.gnu.org/software/autoconf/manual/autoconf-2.57/ +# html_node/autoconf_167.html for further information. +AT_CHECK(MONOTONE import foo, [], ignore, ignore) +... +... +... +AT_CLEANUP +(END) --- tests/t_database_check.at +++ tests/t_database_check.at @@ -60,7 +60,7 @@ AT_CHECK(MONOTONE db execute "delete from files where id='$FILE2'", [], [ignore], [ignore]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep 'database is good' stderr, [1], [ignore], [ignore]) AT_CHECK(grep 'problems detected' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '1 missing file' stderr, [0], [ignore], [ignore]) @@ -74,13 +74,13 @@ AT_CHECK(MONOTONE read < fileX, [], [ignore], [ignore]) AT_CHECK(MONOTONE read < manifestX, [], [ignore], [ignore]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep '1 unreferenced file' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '1 unreferenced manifest' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '7 missing files' stderr, [0], [ignore], [ignore]) AT_CHECK(MONOTONE db execute "delete from revision_ancestry", [], [ignore], [ignore]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep '2 mismatched parent' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '2 mismatched child' stderr, [0], [ignore], [ignore]) @@ -90,34 +90,34 @@ XDELTA_HH="68d15dc01398c7bb375b1a90fbb420bebef1bac7" AT_CHECK(MONOTONE db execute "insert into revision_ancestry values('$XDELTA_CC', '$XDELTA_HH')", [], [ignore], [ignore]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep '3 mismatched parent' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '3 mismatched child' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '2 missing revision' stderr, [0], [ignore], [ignore]) AT_CHECK(MONOTONE db execute "delete from manifest_deltas where id='$MAN1'", [], [ignore], [ignore]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep '1 missing manifest' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '3 revisions with bad history' stderr, [0], [ignore], [ignore]) AT_CHECK(MONOTONE db execute "delete from revisions where id='$REV1'", [], [ignore], [ignore]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep '3 missing revision' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '2 revisions with bad history' stderr, [0], [ignore], [ignore]) echo "$REV2:comment:this is a test:address@hidden:bogus sig" | sha1sum | read HASH AT_CHECK(MONOTONE db execute "insert into revision_certs values ('$HASH', '$REV2', 'comment', 'this is a test', 'address@hidden', 'bogus sig')", [], [ignore], [ignore]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep '1 bad sig' stderr, [0], [ignore], [ignore]) AT_CHECK(MONOTONE db execute "delete from revision_certs where name = 'date'", [], [ignore], [stderr]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep '2 missing certs' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '2 mismatched certs' stderr, [0], [ignore], [ignore]) AT_CHECK(MONOTONE db execute "delete from public_keys", [], [ignore], [stderr]) -AT_CHECK(MONOTONE db check --ticker=dot, [], [ignore], [stderr]) +AT_CHECK(MONOTONE db check --ticker=dot, [1], [ignore], [stderr]) AT_CHECK(grep '1 missing key' stderr, [0], [ignore], [ignore]) AT_CHECK(grep '10 unchecked signatures' stderr, [0], [ignore], [ignore]) --- tests/t_diff_binary.at +++ tests/t_diff_binary.at @@ -1,10 +1,7 @@ AT_SETUP([diff a binary file]) MONOTONE_SETUP NEED_UNGZB64 -# This test is a bug report. -AT_XFAIL_IF(true) - # diff should probably not display the contents of binary files AT_DATA(binary.gz.b64, --- tests/t_netsync_largish_file.at +++ tests/t_netsync_largish_file.at @@ -0,0 +1,35 @@ +AT_SETUP([netsync largish file]) +AT_KEYWORDS([netsync]) + +# Check that we can netsync a 32MB file. + +# We use awk(1) to generate an incompressible file, since the file will be +# compressed in the monotone database and on the wire. + +m4_define([LARGISH_FILE_CREATE], [ +awk -- 'BEGIN{srand(5253);for(a=0;a<32*1024*1024;a+=20)printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256,rand()*256);}' > largish +]) + + +MONOTONE_SETUP +NETSYNC_SETUP + +AT_CHECK(LARGISH_FILE_CREATE) + +AT_CHECK(MONOTONE add largish, [], [ignore], [ignore]) +COMMIT(testbranch) +F_VER0=`SHA1(largish)` + +NETSYNC_SERVE_START(testbranch) + +NETSYNC_CLIENT_RUN(pull, testbranch) + +NETSYNC_SERVE_STOP + +AT_CHECK(MONOTONE --db=test2.db cat file $F_VER0, [], [stdout]) +AT_CHECK(CANONICALISE(stdout)) +CHK=`SHA1(stdout)` +AT_CHECK(test $CHK = $F_VER0) + +AT_CLEANUP + --- tests/t_rename_dir_add_dir_with_old_name.at +++ tests/t_rename_dir_add_dir_with_old_name.at @@ -0,0 +1,28 @@ +# -*- Autoconf -*- + +AT_SETUP([renaming a directory and then adding a new with the old name]) + +MONOTONE_SETUP + +# This test is a bug report. +AT_XFAIL_IF(true) + +# add 'foo/test' file +AT_CHECK(mkdir foo) +AT_DATA(foo/test, [test file in foo dir +]) +AT_CHECK(MONOTONE add foo, [], [ignore], [ignore]) +COMMIT(testbranch) + +# rename 'foo' dir to 'bar' +AT_CHECK(MONOTONE rename foo bar, [], [ignore], [ignore]) +AT_CHECK(mv foo bar) + +# add new 'foo' dir +AT_CHECK(mkdir foo) +AT_DATA(foo/test, [test file in new foo dir +]) +AT_CHECK(MONOTONE add foo, [], [ignore], [ignore]) +COMMIT(testbranch) + +AT_CLEANUP --- tests/t_vcheck.at +++ tests/t_vcheck.at @@ -19,10 +19,9 @@ # The original 'vcheck' was ripped out when manifest and file certs # were removed, and never quite did the right thing anyway. (It only # applied to manifests, in particular.) It may be useful to reference -# the code, though: see, say, -# 727d28b35f1fcbc91c0183fca2a6cabbe7cf21d7, or t:monotone-0.16. In -# particular, mac.hh should be useful. Note also the section -# "Accidental collision" in monotone.texi. +# the code, though: see t:monotone-0.16. In particular, mac.hh should +# be useful. Note also the section "Accidental collision" in +# monotone.texi. # There are a few ways to re-add this. The simplest is probably to # have a cert on revisions that contains @@ -36,6 +35,18 @@ # This reduces space overhead, too, since certs's space usage adds up, # and does so for project members who aren't worried about SHA1 # collisions too... +# +# an alternative approach would be to contain: +# - a salt/nonce +# - a MAC of (length-prefixed revision) + (length prefixed manifest) +# + (length prefixed versions of each file in the manifest, in manifest order) +# this is small, and just as safe. it is rather expensive to create +# or check, though, since you have to load all that data, so maybe the +# optimization above where you only hash mentioned files would be +# good. OTOH, if you hash everything, then you can use them +# sparingly, and be sure that the versions so certed really are safe; +# if you only hash some pieces, you have to cert your entire history +# in order to "trust" any one snapshot at all. AT_CHECK(false) --- testsuite.at +++ testsuite.at @@ -548,5 +548,10 @@ m4_include(tests/t_cvsimport_samelog.at) m4_include(tests/t_sticky_branch.at) m4_include(tests/t_checkout_id_sets_branch.at) +<<<<<<< variant A +m4_include(tests/t_netsync_largish_file.at) m4_include(tests/t_update_off_branch.at) m4_include(tests/t_setup_checkout_modify_new_dir.at) +m4_include(tests/t_rename_dir_add_dir_with_old_name.at) +####### Ancestor +======= end --- ui.cc +++ ui.cc @@ -5,6 +5,7 @@ #include "transforms.hh" #include +#include #include // copyright (C) 2002, 2003 graydon hoare @@ -77,23 +78,35 @@ { } -/// write_ticks flushes progress line with all tickers to 'clog' - * void tick_write_count::write_ticks() +void tick_write_count::write_ticks() { string tickline = "\rmonotone:"; for (map::const_iterator i = ui.tickers.begin(); i != ui.tickers.end(); ++i) { string suffix; - int div = 1; + ostringstream disptick; if (i->second->kilocount && i->second->ticks >= 10000) - { - div = 1024; - suffix = "k"; + { // automatic unit conversion is enabled + float div; + if (i->second->ticks >= 1048576) { + // ticks >=1MB, use Mb + div = 1048576; + suffix = "M"; + } else { + // ticks <1MB, use kb + div = 1024; + suffix = "k"; + } + disptick << std::fixed << std::setprecision(1) << + (i->second->ticks / div); + } else { + // no automatic unit conversion. + disptick << i->second->ticks; } tickline += string(" [") - + i->first + ": " + lexical_cast(i->second->ticks / div) + + i->first + ": " + disptick.str() + suffix + "]"; } @@ -105,7 +118,7 @@ last_tick_len = curr_sz; unsigned int tw = terminal_width(); - if (tickline.size() > tw) + if (tw && tickline.size() > tw) { // first character in tickline is "\r", which does not take up any // width, so we add 1 to compensate. --- win32/process.cc +++ win32/process.cc @@ -1,9 +1,10 @@ // copyright (C) 2005 Jon Bright // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) // see the file COPYING for details #include +#include #include #include "sanity.hh" @@ -34,13 +35,16 @@ realexelen = strlen(argv[0])+1+MAX_PATH; realexe = (char*)malloc(realexelen); if (realexe==NULL) return 0; + L(F("searching for exe: %s\n") % argv[0]); if (SearchPath(NULL, argv[0], ".exe", realexelen, realexe, &filepart)==0) { + L(F("SearchPath failed, err=%d\n") % GetLastError()); free(realexe); return -1; } std::ostringstream cmdline_ss; + L(F("building command line\n")); cmdline_ss << realexe; for (const char *const *i = argv+1; *i; ++i) { @@ -73,6 +77,7 @@ /* We don't need to set any of the STARTUPINFO members */ if (CreateProcess(realexe, (char*)cmd.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)==0) { + L(F("CreateProcess failed, err=%d\n") % GetLastError()); free(realexe); return -1; } --- win32/terminal.cc +++ win32/terminal.cc @@ -5,12 +5,25 @@ // see the file COPYING for details #include +#include +#include + #include "platform.hh" bool have_smart_terminal() { - return true; + std::string term; + if (const char* term_cstr = getenv("TERM")) + term = term_cstr; + else + term = ""; + + if (term == "" || term == "emacs" || term == "dumb" + || !_isatty(_fileno(stdout))) + return false; + else + return true; } unsigned int terminal_width()