# # delete_file "debian/compat" # # delete_file "debian/files" # # delete_file "debian/monotone.1" # # rename_file "contrib/Notify.pl" # to "contrib/monotone-notify.pl" # # rename_file "unix/have_smart_terminal.cc" # to "unix/terminal.cc" # # rename_file "win32/have_smart_terminal.cc" # to "win32/terminal.cc" # # add_file "tests/t_checkout_id_sets_branch.at" # # add_file "tests/t_cvsimport_samelog.at" # # add_file "tests/t_netsync_largish_file.at" # # add_file "tests/t_setup_checkout_modify_new_dir.at" # # add_file "tests/t_sticky_branch.at" # # add_file "tests/t_update_off_branch.at" # # patch "AUTHORS" # from [215e7d83b2c2d5ed5de108e9e9e3f8af01e99131] # to [48363e3c336bf23f49dcd9cc07f1461ec464695e] # # patch "ChangeLog" # from [d0cde54bb8550762927f7c16c848f095c5dd06f5] # to [0ecbb568866836a4805b4d61134f72c2b14c064b] # # patch "Makefile.am" # from [770ce2033048c1013e5d623e65497a11fa78250f] # to [1f3cb32fc6408feb79cd788d61e6864e97815160] # # patch "app_state.cc" # from [d7d6fbd90b19c513269bb0a1b89feab31c681880] # to [63120a266ad19ebd72022cf172ccbd0c299aa413] # # patch "app_state.hh" # from [9e857e19c75141fa7a05592739ce0b9b61d8f706] # to [a239548498beda52f5c4c4488917ef2516cf2fd8] # # patch "cert.cc" # from [1dcf5a6e58a3d626952de7022bec497b7dc19232] # to [f5dc319c1553610d1246dd94f7397669ab09a77f] # # patch "commands.cc" # from [f63e583a3a26df78f0877afd653e1d5244f5c611] # to [958cd3bbc982aef81f63b90b24dcebaddf135166] # # patch "contrib/monotone-notify.pl" # from [3ec4584fa088bf5a60e204219b01bc6ce3520e48] # to [7c66c1b5776bdb8b7a325956ded8502434897906] # # patch "contrib/monotone.bash_completion" # from [fb362f853a667a7f8eb91542f9d67c1880142301] # to [f947568a0d2f341c8a95956f5f84ab250dff4a68] # # patch "debian/docs" # from [27b3b426e26dff78d825cbb511cbb9afbd11475c] # to [269dde6d1f8533595c1ba331f3ecb165502a7c6a] # # patch "monotone.spec" # from [d8d0563f197efb33d4587e16a5b742653fa26b9a] # to [0f11d35fc0ed4ad75e9d2233c74bdb4668fa5815] # # patch "monotone.texi" # from [691c3f74f160470a84b85e44e755b79e2201dc1d] # to [13bed7469b4e155326caade82d7328129accdbec] # # patch "netsync.cc" # from [bcf402c38f32b23aecc664f94d807635ecd04180] # to [8790de4edea2bc9f5cda7d35554b5cebc1de065d] # # patch "platform.hh" # from [1087caf0938a13ff369f293dc42fd2c77802b817] # to [6a6fb903facbfdcce8d50db7a2b3ac8f84fa26d7] # # patch "rcs_import.cc" # from [9e29de36fff479ee09af48f4b037bab8074ef965] # to [4e0b292289773a83cad888d88a347d0423f1ad69] # # patch "tests/t_checkout_id_sets_branch.at" # from [] # to [ea0df0caed46c80391d47ab546e3040c0d54bc1b] # # patch "tests/t_cvsimport.at" # from [140f6332fd7b67c4c58055f2582ce3ee8c4d63df] # to [a212a3cbc77e3bd78bb0bf4aea478769c93dc6d6] # # patch "tests/t_cvsimport_samelog.at" # from [] # to [e7c5ee56f45b0da54ace0fb9282c19604104610d] # # patch "tests/t_netsync_largish_file.at" # from [] # to [0b5e0097e6e6e776b27d24fbe112ca786f27a455] # # patch "tests/t_setup_checkout_modify_new_dir.at" # from [] # to [d3861a3bdaf6b55792cb14000ab5e79f6b00d82b] # # patch "tests/t_sticky_branch.at" # from [] # to [e07f23c47b810968535f7282238be910907a07eb] # # patch "tests/t_update_off_branch.at" # from [] # to [951445e014367f691ff2d44c2018ec13a24daf7b] # # patch "testsuite.at" # from [00ca4539e90331b9ce7fb2861d5b02d621025ba9] # to [14b8600c48fdafc19eba6942e2270738b4bd8c71] # # patch "ui.cc" # from [a5b6fd5aeec52bbcde22cc913046a6f8d67f2f48] # to [f0e2ff249a83fa8a210f961d773ca560bb281592] # # patch "ui.hh" # from [85747d1505f730a42bcdc20e1ef0304bed9995db] # to [7cdd4335a8fa4b4828470eb69b363792bd0a5ce8] # # patch "unix/terminal.cc" # from [153d877da21b373361534ebb2f5b9607e11a4fa9] # to [eef0e6fbdd9455b96654b8f3842c48fbbacfc08e] # # patch "win32/terminal.cc" # from [d90cb7a10d4728b77b293f325f68ef47922513a0] # to [956b84cf7bf5fb26788e77b380935d00291f060e] # --- AUTHORS +++ AUTHORS @@ -46,7 +46,7 @@ Christian Kollee Faheem Mitha Neil Conway - Wojciech Miłkowski + Wojciech Miłkowski Georg-W. Koltermann Daniel Berlin Jon Bright --- ChangeLog +++ ChangeLog @@ -1,3 +1,121 @@ +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. + + * commands.cc (checkout): Tweak branch checking logic. + (update): Make user explicitly switch branches. + +2005-04-13 Nathaniel Smith + + * rcs_import.cc (import_cvs_repo): Check that user isn't trying to + import a whole CVS repo. + * tests/t_cvsimport.at: Test new check. + +2005-04-13 Richard Levitte + + * contrib/Notify.pl: Rename ... + * contrib/monotone-notify.pl: ... to this. + * Makefile.am (EXTRA_DIST): Take note of the change. + * debian/docs: Distribute the contributions as well. + * debian/compat, debian/files, debian/monotone.1: Remove, since + they are self-generated by debhelper. They were obviously added + by mistake. + +2005-04-13 Nathaniel Smith + + * cert.cc (guess_branch): Call app.set_branch. + * app_state.cc (create_working_copy): Call make_branch_sticky + here... + * commands.cc (checkout): ...instead of here. + (approve, disapprove, fcommit, commit): Don't call app.set_branch + on guess_branch's output. + (checkout): Call guess_branch. + + * tests/t_sticky_branch.at: + * tests/t_checkout_id_sets_branch.at: New tests. + * testsuite.at: Add them. + +2005-04-12 Florian Weimer + + * app_state.cc (app_state::allow_working_copy): Only update + branch_name from the options file if it has not yet been set. Log + the branch name. + (app_state::set_branch): No longer update the options map. + (app_state::make_branch_sticky): New function which copies the + stored branch name to the options map. Only commands which call + this function change the branch default stored in the working + copy. + + * commands.cc (CMD(checkout)): Mark branch argument as sticky. + (CMD(commit)): Likewise. + (CMD(update)): Likewise. + + * monotone.texi (Working Copy): Mention that the "commit" and + "update" commands update the stored default branch ("checkout" + does, too, but this one should be obvious). + +2005-04-13 Matthew Gregan + * cryptopp/integer.h: Fix detection of GCC version for SSE2 + builds. + +2005-04-12 Jon Bright + * rcs_import.cc (find_key_and_state): Fix stupid bug in storing the + list of files a cvs_key contains. CVS delta invariant failure now + really fixed. The rearrangement failure still exists, though. + +2005-04-12 Jon Bright + * tests/t_cvsimport_samelog.at: Add test for the deltas.find + cvs import problem as sent to the ML by Emile Snyder. + * testsuite.at: Call it + * rcs_import.cc (cvs_key): Add an ID for debug output purposes, + sprinkle a little more debug output about what's being compared to + what + * rcs_import.cc (cvs_key): Maintain a map of file paths and CVS + versions appearing in this CVS key. + (cvs_key::similar_enough): A key is only similar enough if it doesn't + include a different version of the same file path. + (cvs_history::find_key_and_state): Add files to cvs_keys as + appropriate + +2005-04-12 Matthew Gregan + + * win32/terminal.cc (terminal_width): Use + GetConsoleScreenBufferInfo to request width information for + terminals. + +2005-04-12 Nathaniel Smith + + * ChangeLog: Fixup after merge. + +2005-04-12 Nathaniel Smith + + * platform.hh (terminal_width): New function. + * {unix,win32}/have_smart_terminal.cc: Rename to... + * {unix,win32}/terminal.cc: ...these. Implement terminal_width. + * ui.cc (write_ticks): Call it. + * Makefile.am: Update for renames. + +2005-04-11 Matt Johnston + + * ui.{cc,hh}, netsync.cc: netsync progress ticker in kilobytes to + avoid wrapping. + +2005-04-11 Jon Bright + * Makefile.am (EXTRA_DIST): Add debian/* + +2005-04-11 Jon Bright + * Makefile.am (EXTRA_DIST): Add win32/monotone.iss, PNG_FIGURES + (PNG_FIGURES): Add, constructing in same way as EPS_FIGURES + (monotone.html): Use .perlbak workaround so that this works on Win32 + 2005-04-11 Matt Johnston * unix/inodeprint.cc: use botan for sha1 @@ -14,6 +132,10 @@ * unix/inodeprint.cc, configure.ac: Use nanosecond time resolution for inodeprints on BSDs and other platforms if available. +2005-04-10 Derek Scherger + + * monotone.texi (Informative): fix typo in ls known docs + 2005-04-10 Nathaniel Smith * Makefile.am: Use pdftops instead of acroread. @@ -2605,7 +2727,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 @@ -130,11 +130,11 @@ popt/popt.c popt/popthelp.c popt/system.h UNIX_PLATFORM_SOURCES = \ - unix/read_password.cc unix/get_system_flavour.cc unix/process.cc unix/have_smart_terminal.cc \ + unix/read_password.cc unix/get_system_flavour.cc unix/process.cc unix/terminal.cc \ unix/platform_netsync.cc unix/inodeprint.cc WIN32_PLATFORM_SOURCES = \ - win32/read_password.cc win32/get_system_flavour.cc win32/process.cc win32/have_smart_terminal.cc \ + win32/read_password.cc win32/get_system_flavour.cc win32/process.cc win32/terminal.cc \ win32/platform_netsync.cc win32/inodeprint.cc # primaries @@ -248,12 +248,14 @@ figures/statement.pdf figures/three-versions.pdf \ figures/two-branches.pdf +PNG_FIGURES=$(addprefix $(top_builddir)/figures/,$(notdir $(PDF_FIGURES:.pdf=.png))) EPS_FIGURES=$(addprefix $(top_builddir)/figures/,$(notdir $(PDF_FIGURES:.pdf=.eps))) man1_MANS = monotone.1 info_TEXINFOS = monotone.texi EXTRA_DIST = $(man1_MANS) \ $(PDF_FIGURES) \ + $(PNG_FIGURES) \ INSTALL \ README.changesets \ UPGRADE \ @@ -274,10 +276,12 @@ $(wildcard $(srcdir)/popt/test?.c) popt/testit.sh \ sqlite/keywordhash.h \ contrib/README \ - contrib/Notify.pl \ + contrib/monotone-notify.pl \ contrib/ciabot_monotone.py \ contrib/monotone.el \ - contrib/monotone.bash_completion + contrib/monotone.bash_completion \ + win32/monotone.iss \ + debian/* MAKEINFOFLAGS=-I $(top_builddir) @@ -391,7 +395,8 @@ monotone.html: monotone.texi texinfo.css makeinfo --no-split --no-headers --output $@ --html $< - perl -i -pe 's@@\n@' $@ + perl -i.perlbak -pe 's@@\n@' $@ + rm -f monotone.html.perlbak # The .perlbak thing is needed, otherwise the perl executions fails on MinGW --- app_state.cc +++ app_state.cc @@ -60,7 +60,9 @@ string dbname = absolutify(options[database_option]()); if (dbname != "") db.set_filename(mkpath(dbname)); - branch_name = options[branch_option]; + if (branch_name().empty()) + branch_name = options[branch_option]; + L(F("branch name is '%s'\n") % branch_name()); internalize_rsa_keypair_id(options[key_option], signing_key); if (!current.empty()) @@ -131,6 +133,8 @@ mkdir_p(mt); + make_branch_sticky(); + write_options(); blank_user_log(); @@ -234,8 +238,12 @@ app_state::set_branch(utf8 const & branch) { branch_name = branch(); +} - options[branch_option] = branch; +void +app_state::make_branch_sticky() +{ + options[branch_option] = branch_name(); } void --- app_state.hh +++ app_state.hh @@ -65,7 +65,15 @@ void set_restriction(path_set const & valid_paths, std::vector const & paths); bool restriction_includes(file_path const & path); + // Set the branch name. If you only invoke set_branch, the branch + // name is not sticky (and won't be written to the working copy and + // reused by subsequent monotone invocations). Commands which + // switch the working to a different branch should invoke + // make_branch_sticky (before require_working_copy because this + // function updates the working copy). void set_branch(utf8 const & name); + void make_branch_sticky(); + void set_database(utf8 const & filename); void set_signing_key(utf8 const & key); void set_root(utf8 const & root); --- cert.cc +++ cert.cc @@ -488,6 +488,7 @@ "please provide a branch name") % ident); decode_base64(certs[0].inner().value, branchname); + app.set_branch(branchname()); } } --- commands.cc +++ commands.cc @@ -1329,8 +1329,7 @@ complete(app, idx(args, 0)(), r); packet_db_writer dbw(app); cert_value branchname; - guess_branch (r, app, branchname); - app.set_branch(branchname()); + guess_branch(r, app, branchname); N(app.branch_name() != "", F("need --branch argument for approval")); cert_revision_in_branch(r, app.branch_name(), app, dbw); } @@ -1352,8 +1351,7 @@ F("revision %s has %d changesets, cannot invert\n") % r % rev.edges.size()); cert_value branchname; - guess_branch (r, app, branchname); - app.set_branch(branchname()); + guess_branch(r, app, branchname); N(app.branch_name() != "", F("need --branch argument for disapproval")); edge_entry const & old_edge (*rev.edges.begin()); @@ -1545,8 +1543,7 @@ dbw.consume_revision_data(new_rid, rdata); // take care of any extra certs - guess_branch (old_rid, app, branchname); - app.set_branch(branchname()); + guess_branch(old_rid, app, branchname); if (args.size() == 3) log_message = idx(args, 2)(); @@ -1777,7 +1774,6 @@ if (args.size() == 0 || args.size() == 1) { N(app.branch_name() != "", F("need --branch argument for branch-based checkout")); - // if no checkout dir specified, use branch name if (args.size() == 0) dir = app.branch_name(); @@ -1796,25 +1792,29 @@ { dir = idx(args, 1)(); complete(app, idx(args, 0)(), ident); + + { + cert_value b; + guess_branch(ident, app, b); + } + { + I(!app.branch_name().empty()); + cert_value branch_name(app.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(F("found %d %s branch certs on revision %s\n") + % certs.size() + % app.branch_name + % ident); + + N(certs.size() != 0, F("revision %s is not a member of branch %s\n") + % ident % app.branch_name); + } - if (!app.branch_name().empty()) - { - cert_value branch_name(app.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(F("found %d %s branch certs on revision %s\n") - % certs.size() - % app.branch_name - % ident); - - N(certs.size() != 0, F("revision %s is not a member of branch %s\n") - % ident % app.branch_name); - } - app.create_working_copy(dir); } @@ -2549,6 +2549,7 @@ revision_id rid; manifest_map m_old, m_new; + app.make_branch_sticky(); app.require_working_copy(); // preserve excluded work for future commmits @@ -2563,8 +2564,7 @@ cert_value branchname; I(rs.edges.size() == 1); - guess_branch (edge_old_revision(rs.edges.begin()), app, branchname); - app.set_branch(branchname()); + guess_branch(edge_old_revision(rs.edges.begin()), app, branchname); P(F("beginning commit on branch '%s'\n") % branchname); L(F("new manifest %s\n") % rs.new_manifest); @@ -3112,6 +3112,8 @@ if (args.size() != 0 && args.size() != 1) throw usage(name); + if (!app.branch_name().empty()) + app.make_branch_sticky(); app.require_working_copy(); calculate_current_revision(app, r_working, m_old, m_working); @@ -3147,8 +3149,24 @@ P(F("already up to date at %s\n") % r_old_id); return; } + + P(F("selected update target %s\n") % r_chosen_id); - P(F("selected update target %s\n") % r_chosen_id); + if (!app.branch_name().empty()) + { + cert_value branch_name(app.branch_name()); + base64 branch_encoded; + encode_base64(branch_name, branch_encoded); + + vector< revision > certs; + app.db.get_revision_certs(r_chosen_id, branch_cert_name, branch_encoded, certs); + + N(certs.size() != 0, + F("revision %s is not a member of branch %s\n" + "try again with explicit --branch\n") + % r_chosen_id % app.branch_name); + } + app.db.get_revision_manifest(r_chosen_id, m_chosen_id); app.db.get_manifest(m_chosen_id, m_chosen); --- contrib/monotone-notify.pl +++ contrib/monotone-notify.pl @@ -279,6 +279,8 @@ my $message_count = 0; # It's nice with a little bit of statistics. + my $message_count = 0; # It's nice with a little bit of statistics. + foreach my $date (sort keys %timeline) { foreach my $revision (keys %{$timeline{$date}}) { foreach my $sendinfo (([ 1, "Notify.debug-diffs", $difflogs_to ], @@ -624,11 +626,12 @@ =head1 NAME -Notify.pl - a script to send monotone change notifications by email +monotone-notify.pl - a script to send monotone change notifications by email =head1 SYNOPSIS -Notify.pl [--help] [--man] [--db=database] [--root=path] [--branch=branch ...] +monotone-notify.pl [--help] [--man] +[--db=database] [--root=path] [--branch=branch ...] [--[no]update] [--[no]mail] [--[no]attachments] [--from=email-sender] [--difflogs-to=email-recipient] [--nodifflogs-to=email-recipient] @@ -637,9 +640,10 @@ =head1 DESCRIPTION -B is used to generate emails containing monotone change -logs for recent changes. It uses monotone database variables in the -domain 'notify' to keep track of the latest revisions already logged. +B is used to generate emails containing monotone +change logs for recent changes. It uses monotone database variables +in the domain 'notify' to keep track of the latest revisions already +logged. =head1 OPTIONS @@ -672,8 +676,8 @@ =item B<--update> -Has Notify.pl update the database variables at the end of the run. -This is the default unless B<--debug> is given. +Has B update the database variables at the end of +the run. This is the default unless B<--debug> is given. =item B<--noupdate> @@ -682,8 +686,8 @@ =item B<--mail> -Has Notify.pl send the constructed logs as emails. This is the -default unless B<--debug> is given. +Has B send the constructed logs as emails. This +is the default unless B<--debug> is given. =item B<--nomail> @@ -742,15 +746,15 @@ =item B<--debug> -Makes Notify.pl go to debug mode. It means a LOT of extra output, and -also implies B<--noupdate> and B<--nomail> unless specified -differently on the command line. +Makes B go to debug mode. It means a LOT of extra +output, and also implies B<--noupdate> and B<--nomail> unless +specified differently on the command line. =item B<--quiet> -Makes Notify.pl really silent. It will normally produce a small log -of it's activities, but with B<--quiet>, it will only output error -messages. If B<--debug> was given, B<--quiet> is turned off +Makes B really silent. It will normally produce a +small log of it's activities, but with B<--quiet>, it will only output +error messages. If B<--debug> was given, B<--quiet> is turned off unconditionally. =back @@ -763,12 +767,12 @@ other means to move changes from one branch to another. This behavior isn't entirely deterministic, as it depends on when the -last run of Notify.pl was done, and what head revisions were active at -that time. It might be seen as a bug, but if corrected, it might miss -out on development that moves entirely to another branch and moves -back later in time, thereby creating a hole in the branch currently -looked at. This has actually happened in the development of monotone -itself. +last run of B was done, and what head revisions +were active at that time. It might be seen as a bug, but if +corrected, it might miss out on development that moves entirely to +another branch and moves back later in time, thereby creating a hole +in the branch currently looked at. This has actually happened in the +development of monotone itself. For now, it's assumed that a little too much information is better than (unjust) lack of information. --- contrib/monotone.bash_completion +++ contrib/monotone.bash_completion @@ -1,6 +1,6 @@ # -*- shell-script -*- -# bash completion for monotone 0.17 +# bash completion for monotone 0.18 # Author: Olivier Andrieu # source this file from your .bashrc @@ -52,6 +52,14 @@ mono_db="$w" ; break fi done + if [ -z "$mono_db" ] ; then + for i in address@hidden ; do + [ $i -eq 0 ] && continue + if [ "${COMP_WORDS[$i-1]}" == --db ] ; then + mono_db="--db=${COMP_WORDS[$i]}" ; break + fi + done + fi case $cur in --db=* | --rcfile=* | --dump=* ) @@ -72,17 +80,32 @@ _monotone_complete revision ;; -* ) - COMPREPLY=( $(compgen -W '--debug --dump= --quiet --help --nostd --norc\ - --rcfile= --key= --db= --branch= --version --full-version\ - --ticker= --revision= --message=' -- $cur) ) + COMPREPLY=( $(compgen -W '--debug --dump --quiet --help --nostd --norc\ + --rcfile --key --db --branch --version --full-version\ + --ticker --revision --message' -- $cur) ) ;; * ) case $prev in + --db | -d | --rcfile | --dump ) + _filedir + ;; + --branch | -b ) + _monotone_branches + ;; + --key | -k ) + _monotone_keys pubkey + ;; + --ticker ) + COMPREPLY=( $(compgen -W 'count dot' -- $cur ) ) + ;; + --revision | -r ) + _monotone_complete revision + ;; db ) COMPREPLY=( $(compgen -W 'init info version dump load migrate execute check changesetify rebuild' -- $cur ) ) ;; cdiff | diff ) - COMPREPLY=( $(compgen -W '--revision=' -- $cur ) ) + COMPREPLY=( $(compgen -W '--revision' -- $cur ) ) _filedir ;; log | approve | disapprove | comment | tag | testresult | cert | explicit_merge | trusted | update ) --- debian/docs +++ debian/docs @@ -1,3 +1,4 @@ NEWS README html +contrib --- monotone.spec +++ monotone.spec @@ -21,18 +21,21 @@ %setup -q %build +CFLAGS="$RPM_OPT_FLAGS" \ +CXXFLAGS="$RPM_OPT_FLAGS" \ ./configure --prefix=$RPM_BUILD_ROOT/usr \ --infodir=$RPM_BUILD_ROOT%{_infodir} \ --mandir=$RPM_BUILD_ROOT%{_mandir} \ --with-bundled-sqlite \ - --with-bundled-lua \ - --enable-static-boost + --with-bundled-lua make %install rm -rf $RPM_BUILD_ROOT make install rm -f $RPM_BUILD_ROOT%{_infodir}/dir +# remove x permission in contrib to avoid messing the dependencies +chmod -x contrib/* %clean rm -rf $RPM_BUILD_ROOT @@ -52,7 +55,7 @@ %files %defattr(-,root,root,-) -%doc AUTHORS COPYING NEWS README README.changesets UPGRADE +%doc AUTHORS COPYING NEWS README README.changesets UPGRADE contrib %{_bindir}/monotone %{_mandir}/man1/monotone.1.gz %{_infodir}/*.info*.gz --- monotone.texi +++ monotone.texi @@ -3288,6 +3288,10 @@ If the commit is successful, the @file{MT/log} file is cleared of all content making it ready for another edit/commit cycle. +If a @option{--branch} option is specified, the @command{commit} command +commits to this branch (creating it if necessary). The branch becomes +the new default branch of the working copy. + The @command{commit} command also synthesizes a number of certificates, which it attaches to the new manifest version and copies into your database: @@ -3364,6 +3368,11 @@ specified, with your local changes (and only your local changes) applied. +If a @option{--branch} option is specified, the @command{update} command +tries to select the revision to update to from this branch. The branch +becomes the new default branch of the working copy (even if you also +specify an explicit @var{revision} argument). + @end ftable @page @@ -3637,7 +3646,7 @@ From within a subdirectory of the working copy the @command{list known} command will, by default, search the entire working copy. -Specifying only the pathname "." will restrict the search for unknown +Specifying only the pathname "." will restrict the search for known files to the current subdirectory of the working copy. @item monotone list unknown --- netsync.cc +++ netsync.cc @@ -2884,8 +2884,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)); - sess.byte_out_ticker.reset(new ticker("bytes out", "<", 256)); + sess.byte_in_ticker.reset(new ticker("bytes in", ">", 256, true)); + sess.byte_out_ticker.reset(new ticker("bytes out", "<", 256, true)); if (role == sink_role) { sess.cert_in_ticker.reset(new ticker("certs in", "c", 3)); --- platform.hh +++ platform.hh @@ -26,6 +26,10 @@ // for term selection bool have_smart_terminal(); +// this function cannot call W/P/L, because it is called by the tick printing +// code. +// return value of 0 means "unlimited" +unsigned int terminal_width(); // for netsync void start_platform_netsync(); --- rcs_import.cc +++ rcs_import.cc @@ -64,17 +64,36 @@ inline bool similar_enough(cvs_key const & other) const { + L(F("Checking similarity of %d and %d\n") % id % other.id); if (changelog != other.changelog) return false; if (author != other.author) return false; if (labs(time - other.time) > constants::cvs_window) return false; + for (map::const_iterator it = files.begin(); it!=files.end(); it++) + { + map::const_iterator otherit; + +L(F("checking %s %s\n") % it->first % it->second); + otherit = other.files.find(it->first); + if (otherit != other.files.end() && it->second!=otherit->second) + { + L(F("!similar_enough: %d/%d\n") % id % other.id); + return false; + } +else if (otherit != other.files.end()) +{ +L(F("Same file, different version: %s and %s\n") % it->second % otherit->second); +} + } + L(F("similar_enough: %d/%d\n") % id % other.id); return true; } inline bool operator==(cvs_key const & other) const { + L(F("Checking equality of %d and %d\n") % id % other.id); return branch == other.branch && changelog == other.changelog && author == other.author && @@ -99,12 +118,24 @@ && branch > other.branch); } + inline void add_file(file_path const &file, string const &version) + { + L(F("Adding file %s version %s to %d\n") % file % version % id); + files.insert( make_pair(file, version) ); + } + cvs_branchname branch; cvs_changelog changelog; cvs_author author; time_t time; + map files; // Maps file to version + int id; // Only used for debug output + + static int nextid; // Used to initialise id }; +int cvs_key::nextid = 0; + struct cvs_file_edge { @@ -726,6 +757,7 @@ #endif time=mktime(&t); L(F("= %i\n") % time); + id = nextid++; } string branch_name = find_branch_for_version(r.admin.symbols, @@ -772,6 +804,7 @@ map< cvs_key, shared_ptr > & substates = stk.top()->substates; cvs_key nk(r, version, *this); + nk.add_file(curr_file, version); // key+(window/2) is in the future, key-(window/2) is in the past. the // past is considered "greater than" the future in this map, so we take: // @@ -798,6 +831,9 @@ { key = i->first; state = i->second; + key.add_file(curr_file, version); + substates.erase(i->first); + substates.insert(make_pair(key, state)); return true; } } @@ -1249,6 +1285,10 @@ import_cvs_repo(fs::path const & cvsroot, app_state & app) { + N(!fs::exists(cvsroot / "CVSROOT"), + F("%s appears to be a CVS repository root directory\n" + "try importing a module instead, with 'cvs_import %s/") + % cvsroot.native_directory_string() % cvsroot.native_directory_string()); { // early short-circuit to avoid failure after lots of work --- tests/t_checkout_id_sets_branch.at +++ tests/t_checkout_id_sets_branch.at @@ -0,0 +1,27 @@ +AT_SETUP([checkout without --branch sets branch]) +MONOTONE_SETUP + +ADD_FILE(foo, [blah blah +]) +COMMIT(testbranch) +REV=`BASE_REVISION` + +AT_CHECK(MONOTONE checkout $REV codir1, [], [ignore], [ignore]) +AT_CHECK(cmp foo codir1/foo) +AT_DATA(codir1/foo, [hi maude +]) +# verify that no branch is needed for commit +AT_CHECK(cd codir1 && MONOTONE commit --message=foo, [], [ignore], [ignore]) + +AT_CHECK(MONOTONE cert $REV branch otherbranch) + +# but, now we can't checkout without a --branch... +# need to make sure don't pick up branch from our local MT dir... +AT_CHECK(rm -rf MT) +AT_CHECK(MONOTONE checkout $REV codir2, [1], [ignore], [ignore]) +AT_CHECK(MONOTONE checkout $REV --branch=testbranch codir3, [], [ignore], [ignore]) +AT_CHECK(cmp foo codir3/foo) +AT_CHECK(MONOTONE checkout $REV --branch=otherbranch codir4, [], [ignore], [ignore]) +AT_CHECK(cmp foo codir4/foo) + +AT_CLEANUP --- tests/t_cvsimport.at +++ tests/t_cvsimport.at @@ -46,6 +46,9 @@ # import into monotone and check presence of files +# safety check -- we stop people from accidentally feeding their whole +# repo to cvs_import instead of just a module. +AT_CHECK(MONOTONE --branch=testbranch cvs_import $CVSROOT, [1], [ignore], [ignore]) AT_CHECK(MONOTONE --branch=testbranch cvs_import $CVSROOT/testdir, [], [ignore], [ignore]) AT_CHECK(MONOTONE cat file $TSHA0, [], [ignore]) AT_CHECK(MONOTONE cat file $TSHA1, [], [ignore]) --- tests/t_cvsimport_samelog.at +++ tests/t_cvsimport_samelog.at @@ -0,0 +1,61 @@ +# -*- Autoconf -*- + +AT_SETUP([importing CVS files with identical logs]) + +MONOTONE_SETUP + +AT_DATA(importme.0, [version 0 of test file +]) + +AT_DATA(importme.1, [version 1 of test file +]) + +AT_DATA(importme.2, [version 2 of test file +]) + +AT_DATA(importme.3, [version 3 of test file +]) + +TSHA0=`SHA1(importme.0)` +TSHA1=`SHA1(importme.1)` +TSHA2=`SHA1(importme.2)` +TSHA3=`SHA1(importme.3)` + +# build the cvs repository + +CVSROOT=`pwd`/cvs-repository +AT_CHECK(cvs -q -d $CVSROOT init) +AT_CHECK(test -e $CVSROOT) +AT_CHECK(test -e $CVSROOT/CVSROOT) +AT_CHECK(test -e $CVSROOT/CVSROOT/history) + +# check out the working copy and make some commits + +AT_CHECK(cvs -d $CVSROOT co ., [], [ignore], [ignore]) +AT_CHECK(mkdir testdir) +AT_CHECK(cp importme.0 testdir/importme) +AT_CHECK(cvs -d $CVSROOT add testdir, [], [ignore], [ignore]) +AT_CHECK(cvs -d $CVSROOT add testdir/importme, [], [ignore], [ignore]) +AT_CHECK(cvs -d $CVSROOT commit -m 'commit 0' testdir/importme, [], [ignore], [ignore]) +AT_CHECK(cp importme.1 testdir/importme) +AT_CHECK(cvs -d $CVSROOT commit -m 'commit same message' testdir/importme, [], [ignore], [ignore]) +AT_CHECK(cp importme.2 testdir/importme) +AT_CHECK(cvs -d $CVSROOT commit -m 'commit same message' testdir/importme, [], [ignore], [ignore]) +AT_CHECK(cp importme.3 testdir/importme) +AT_CHECK(cvs -d $CVSROOT commit -m 'commit 3' testdir/importme, [], [ignore], [ignore]) + +# import into monotone and check presence of files + +AT_CHECK(MONOTONE --branch=testbranch cvs_import $CVSROOT/testdir, [], [ignore], [ignore]) +AT_CHECK(MONOTONE cat file $TSHA0, [], [ignore]) +AT_CHECK(MONOTONE cat file $TSHA1, [], [ignore]) +AT_CHECK(MONOTONE cat file $TSHA2, [], [ignore]) +AT_CHECK(MONOTONE cat file $TSHA3, [], [ignore]) + +# also check that history is okay -- has a unique head, and it's the +# right one. + +AT_CHECK(MONOTONE checkout --branch=testbranch mtcodir, [], [ignore], [ignore]) +AT_CHECK(cmp importme.3 mtcodir/importme) + +AT_CLEANUP --- 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_setup_checkout_modify_new_dir.at +++ tests/t_setup_checkout_modify_new_dir.at @@ -0,0 +1,30 @@ +AT_SETUP([setup/checkout touch new MT/options only]) +MONOTONE_SETUP + +ADD_FILE(foo, [blah blah +]) +COMMIT(testbranch) + +# okay, now wd is on testbranch + +# setup a dir on otherbranch and make sure we stay on testbranch +AT_CHECK(MONOTONE setup setupdir --branch=otherbranch, [], [ignore], [ignore]) +SET_FILE(foo, [stuff stuff +]) +AT_CHECK(MONOTONE commit --message=foo, [], [ignore], [ignore]) +CHECK_SAME_STDOUT(BASE_REVISION, MONOTONE automate heads testbranch) + +# now create a revision in otherbranch... +AT_DATA(setupdir/blah, [yum yum +]) +AT_CHECK(cd setupdir && MONOTONE add blah, [], [ignore], [ignore]) +AT_CHECK(cd setupdir && MONOTONE commit --message=foo, [], [ignore], [ignore]) +# and check it out +AT_CHECK(MONOTONE checkout codir --branch=otherbranch, [], [ignore], [ignore]) +# and make sure we still stayed on testbranch +SET_FILE(foo, [more more +]) +AT_CHECK(MONOTONE commit --message=foo, [], [ignore], [ignore]) +CHECK_SAME_STDOUT(BASE_REVISION, MONOTONE automate heads testbranch) + +AT_CLEANUP --- tests/t_sticky_branch.at +++ tests/t_sticky_branch.at @@ -0,0 +1,67 @@ +AT_SETUP([sticky branches]) +MONOTONE_SETUP + +# setup saves given branch +AT_CHECK(MONOTONE setup setupdir --branch=testbranch, [], [ignore], [ignore]) +AT_DATA(setupdir/foo, [blah blah +]) +AT_CHECK(cd setupdir && MONOTONE add foo, [], [ignore], [ignore]) +AT_CHECK(cd setupdir && MONOTONE commit --message=foo, [], [ignore], [ignore]) + +# checkout saves given branch +AT_CHECK(MONOTONE checkout --branch=testbranch codir, [], [ignore], [ignore]) +AT_CHECK(cmp setupdir/foo codir/foo) +AT_DATA(codir/foo, [other other +]) +AT_CHECK(cd codir && MONOTONE commit --message=foo, [], [ignore], [ignore]) + +# log doesn't affect given branch +AT_CHECK(cd codir && MONOTONE log --branch=otherbranch, [], [ignore], [ignore]) +AT_DATA(codir/foo, [more more +]) +AT_CHECK(cd codir && MONOTONE commit --message=foo, [], [ignore], [ignore]) +AT_CHECK(MONOTONE ls branches, [], [testbranch +], []) + +# commit saves given branch +AT_DATA(codir/foo, [newbranch newbranch +]) +AT_CHECK(cd codir && MONOTONE commit --branch=otherbranch --message=foo, [], [ignore], [ignore]) +AT_DATA(codir/foo, [newbranch 2 newbranch 2 +]) +AT_CHECK(cd codir && MONOTONE commit --message=foo, [], [ignore], [ignore]) +AT_CHECK(MONOTONE checkout --branch=otherbranch otherdir, [], [ignore], [ignore]) +AT_CHECK(cmp codir/foo otherdir/foo) + +# update saves the given branch +AT_CHECK(MONOTONE checkout --branch=testbranch updir, [], [ignore], [ignore]) +AT_CHECK(cd updir && MONOTONE update --branch=otherbranch, [], [ignore], [ignore]) +AT_CHECK(cmp otherdir/foo updir/foo) +AT_DATA(otherdir/foo, [yet another chunk of entropy +]) +AT_CHECK(cd otherdir && MONOTONE commit --message=foo, [], [ignore], [ignore]) +AT_CHECK(cd updir && MONOTONE update, [], [ignore], [ignore]) +AT_CHECK(cmp otherdir/foo updir/foo) + +# merge doesn't affect given branch +AT_CHECK(MONOTONE setup third1, [], [ignore], [ignore]) +AT_DATA(third1/a, [1a +]) +AT_CHECK(cd third1 && MONOTONE add a, [], [ignore], [ignore]) +AT_CHECK(cd third1 && MONOTONE commit --branch=third --message=foo, [], [ignore], [ignore]) +AT_CHECK(MONOTONE setup third2, [], [ignore], [ignore]) +AT_DATA(third2/b, [2b +]) +AT_CHECK(cd third2 && MONOTONE add b, [], [ignore], [ignore]) +AT_CHECK(cd third2 && MONOTONE commit --branch=third --message=foo, [], [ignore], [ignore]) +AT_CHECK(cd codir && MONOTONE merge --branch=third, [], [ignore], [ignore]) +AT_CHECK(MONOTONE automate heads third, [], [stdout], [ignore]) +AT_CHECK(mv stdout old-third-heads) +AT_DATA(codir/foo, [more more +]) +AT_CHECK(cd codir && MONOTONE commit --message=foo, [], [ignore], [ignore]) +# we check that this didn't create a new head of branch third +AT_CHECK(MONOTONE automate heads third, [], [stdout], [ignore]) +AT_CHECK(cmp stdout old-third-heads) + +AT_CLEANUP --- tests/t_update_off_branch.at +++ tests/t_update_off_branch.at @@ -0,0 +1,18 @@ +AT_SETUP([update to off-branch rev]) +MONOTONE_SETUP + +ADD_FILE(testfile, [blah blah +]) +COMMIT(testbranch) +TR=`BASE_REVISION` + +SET_FILE(testfile, [other other +]) +COMMIT(otherbranch) +OR=`BASE_REVISION` + +AT_CHECK(MONOTONE checkout --branch=testbranch $TR codir, [], [ignore], [ignore]) +AT_CHECK(cd codir && MONOTONE update $OR, [1], [ignore], [ignore]) +AT_CHECK(cd codir && MONOTONE update --branch=otherbranch $OR, [], [ignore], [ignore]) + +AT_CLEANUP --- testsuite.at +++ testsuite.at @@ -545,3 +545,9 @@ m4_include(tests/t_inodeprints.at) m4_include(tests/t_inodeprints_update.at) m4_include(tests/t_ls_known.at) +m4_include(tests/t_cvsimport_samelog.at) +m4_include(tests/t_sticky_branch.at) +m4_include(tests/t_checkout_id_sets_branch.at) +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) --- ui.cc +++ ui.cc @@ -20,9 +20,11 @@ using boost::lexical_cast; struct user_interface ui; -ticker::ticker(string const & tickname, std::string const & s, size_t mod) : +ticker::ticker(string const & tickname, std::string const & s, size_t mod, + bool kilocount) : ticks(0), mod(mod), + kilocount(kilocount), name(tickname), shortname(s) { @@ -77,14 +79,22 @@ void tick_write_count::write_ticks() { - string tickline = "\rmonotone: "; + string tickline = "\rmonotone:"; for (map::const_iterator i = ui.tickers.begin(); i != ui.tickers.end(); ++i) { + string suffix; + int div = 1; + if (i->second->kilocount && i->second->ticks >= 10000) + { + div = 1024; + suffix = "k"; + } tickline += - string("[") - + i->first + ": " + lexical_cast(i->second->ticks) - + "] "; + string(" [") + + i->first + ": " + lexical_cast(i->second->ticks / div) + + suffix + + "]"; } tickline += ui.tick_trailer; @@ -93,6 +103,14 @@ tickline += string(last_tick_len - curr_sz, ' '); last_tick_len = curr_sz; + unsigned int tw = terminal_width(); + if (tw && tickline.size() > tw) + { + // first character in tickline is "\r", which does not take up any + // width, so we add 1 to compensate. + tickline.resize(tw + 1); + } + clog << tickline; clog.flush(); } --- ui.hh +++ ui.hh @@ -21,9 +21,11 @@ { size_t ticks; size_t mod; + bool kilocount; std::string name; std::string shortname; - ticker(std::string const & n, std::string const & s, size_t mod = 64); + ticker(std::string const & n, std::string const & s, size_t mod = 64, + bool kilocount=false); void operator++(); void operator+=(size_t t); ~ticker(); --- unix/terminal.cc +++ unix/terminal.cc @@ -1,17 +1,22 @@ // copyright (C) 2005 derek scherger +// copyright (C) 2005 nathaniel smith // 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 #include +#include "platform.hh" + bool have_smart_terminal() { std::string term; - if (char* term_cstr = getenv("TERM")) + if (const char* term_cstr = getenv("TERM")) term = term_cstr; else term = ""; @@ -22,3 +27,18 @@ else return true; } + +unsigned int terminal_width() +{ + struct winsize ws; + int ret = ioctl(2, TIOCGWINSZ, &ws); + if (ret < 0) + { + // FIXME: it would be nice to log something here + // but we are called by the tick printing code, and trying to print + // things while in the middle of printing a tick line is a great way to + // break things. + return 0; + } + return ws.ws_col; +} --- win32/terminal.cc +++ win32/terminal.cc @@ -1,11 +1,30 @@ // copyright (C) 2005 derek scherger +// copyright (C) 2005 nathaniel smith // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) // see the file COPYING for details +#include + #include "platform.hh" bool have_smart_terminal() { return true; } + +unsigned int terminal_width() +{ + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + if (h != INVALID_HANDLE_VALUE) + { + CONSOLE_SCREEN_BUFFER_INFO ci; + if (GetConsoleScreenBufferInfo(h, &ci) != 0) + { + return static_cast(ci.dwSize.X); + } + } + + // default to 80 columns if the width query failed. + return 80; +}