# # add_file "hmac.cc" # # add_file "hmac.hh" # # patch "AUTHORS" # from [1bc23bee8e818ed6bc3b2d173b0f6435cbc92832] # to [ff466bec33fb81e11e8f7dc8cc425e89ee70f745] # # patch "ChangeLog" # from [dbed68c08f5bbda72e46fd6f3a557246e9f585a6] # to [81eece5640970d2c6a838995ff56ed60e0868cd9] # # patch "Makefile.am" # from [78ca8f5e5c7726ed29bf7ebd7db41367e8af60ae] # to [cbd9fbc3d73a88f56a538bc5050a2ce3a2ffee31] # # patch "commands.cc" # from [6d3576bd14d6e1fe8c595a75dcf50a478e6f1f65] # to [c9dd7afdabd028f1a9ec18da9aa1a9de1670765d] # # patch "constants.cc" # from [2258f6165b6db8f8c952f97aaacf0addbbed060f] # to [dcbffe20599c26310957ee7c1310a44ae93dc2a0] # # patch "contrib/mtbrowse.sh" # from [be25d5887954500c958377bc524161d7a641fcaa] # to [9ad2130061d1372f803e9b59e3f45bf38609c31a] # # patch "file_io.cc" # from [6125dbcc50e69e63ba8a22664e3e8126ee1115a0] # to [ff47ce57304e48a07f9e6c539610f7d992c5e773] # # patch "hmac.cc" # from [] # to [39bc2c1c84cb059b9d4095dd23daa369c33c4cbf] # # patch "hmac.hh" # from [] # to [1aca898a8a90b9054cd1b4c0e966b298854cc924] # # patch "netcmd.cc" # from [d6a4b557b616231cd233f2935c5c3c9cae327362] # to [b8f2bfffbb6ebefdf274ea1d5ac59b58cd837671] # # patch "netcmd.hh" # from [6054b45890695d2e78404a82f9f2bc6b85ca8330] # to [f6262bdd5719defdd5ef6237e090687701ef4006] # # patch "netsync.cc" # from [9715316b0883fb6d8dbfd0c524ee617c4a0225a4] # to [f1056e86785d18c2a7da04c76086fd3c5106ab9c] # # patch "revision.cc" # from [277c60b5acdedb97fe5cf8930b5f5452063abfd8] # to [dab8f8c33fc1b34f01958d267e98164a96e52738] # # patch "tests/t_diff_currev.at" # from [a14fc00cd1a98b790f305ec3ea257c9c2406639b] # to [ee9a2d74b230a17a54292a4b2301f650330bf3ea] # # patch "transforms.cc" # from [fe0f025921c7a342635e152d4f7c8b93499be401] # to [589f2e927da5c33a2adb9bfea8f9b70d041ce212] # # patch "transforms.hh" # from [446f1de66317ee1a5a4ee76fd0887a686c8264b8] # to [9f9adf9a36619e493cceea57d78e6c4cc456598d] # # patch "vocab.hh" # from [77bb3d7df9abc7e4e5202cb20b313c925dad2c13] # to [e7d7947fe544166a511b44911cff89fa62ace2e9] # --- AUTHORS +++ AUTHORS @@ -60,6 +60,7 @@ Matthew Gregan Riccardo Ghetta Ethan Blanton + Eric Anderson supporting files: ----------------- --- ChangeLog +++ ChangeLog @@ -93,6 +93,32 @@ * transforms.hh (glob_to_regex, globs_to_regex, regexes_to_regex): Prototype. +2005-06-28 Matt Johnston + + * constants.cc: increase db_version_cache_sz to 7 MB + * netsync.cc: use a deque rather than a single + string buffer for outbuf. + * netsync.cc (arm): only queue data when there is + available space + * AUTHORS: added Eric Anderson + +2005-06-26 Matt Johnston + + * transforms.hh: remove extraneous #ifdef + * hmac.cc, hmac.hh: actually add them + +2005-06-26 Matt Johnston + + * netcmd.cc (netcmd::read, netcmd::write): change to using a HMACs + chained by including the previous HMAC in the input data, rather + than altering the key each time. + * netcmd.cc ({read,write}_{data,delta}_cmd): use encode_gzip/decode_gzip + rather than raw xform. + * hmac.{cc,hh}: new chained_hmac abstraction + * Makefile.in: add them + * netsync.cc: each session keeps a chained_hmac for read/write + * transforms.hh: add a string variant for encode_gzip + 2005-06-25 Nathaniel Smith * netsync.cc: Tweak comment. @@ -159,6 +185,57 @@ lua excerpts from hook reference. * Makefile.am : make monotone.pdf/eps depend on monotone.info +2005-06-24 Matt Johnston + + * transforms.{cc,hh}: combine gzip and base64 in one + pipe for pack()/unpack() to save memory + * vocab.hh: add swap() to encodings/atomics + * file_io.cc: use swap() to avoid copying + +2005-06-21 Nathaniel Smith + + * commands.cc (do_diff): Use calculate_arbitrary_change_set, + instead of reimplementing it. + +2005-06-21 Nathaniel Smith + + * revision.cc (find_least_common_ancestor): Handle left == right + case. + * tests/t_diff_currev.at: Un-XFAIL. + +2005-06-21 Nathaniel Smith + + * netsync.cc (rebuild_merkle_trees): Fix FIXME comments to match + reality. + * tests/t_netsync_diffbranch.at: No longer a bug, remove + priority. + +2005-06-20 Nathaniel Smith + + * monotone.texi (Hook Reference): Oops, missed a @ref. + +2005-06-20 Nathaniel Smith + + * monotone.texi (Default monotonerc): Rename section to... + (Default hooks): ...this, to emphasize is still read even when a + monotonerc exists. + +2005-06-19 Richard Levitte + + * Makefile.am: There's no reason for monotone.pdf or .dvi to + depend on monotone.info, since they are built from the .texi + files. Also, make the monotone.html and html targets depend + on version.texi and std_hooks.lua as well. + +2005-06-18 Matt Johnston + + * INSTALL: fix typo, should be -Iboost_1_31_0 not -Iboost_1_31_2 + +2005-06-18 Riccardo Ghetta + * monotone.texi: include std_hooks.lua as an appendix and remove long + lua excerpts from hook reference. + * Makefile.am : make monotone.pdf/eps depend on monotone.info + 2005-06-17 Matt Johnston * database.cc (database::execute()): truncate long query log messages --- Makefile.am +++ Makefile.am @@ -40,6 +40,7 @@ selectors.cc selectors.hh \ annotate.cc annotate.hh \ restrictions.cc restrictions.hh \ + hmac.cc hmac.hh \ globish.cc globish.hh \ \ cleanup.hh unit_tests.hh interner.hh \ --- commands.cc +++ commands.cc @@ -2662,36 +2662,8 @@ N(find_least_common_ancestor(src_id, dst_id, anc_id, app), F("no common ancestor for %s and %s") % src_id % dst_id); - if (src_id == anc_id) - { - calculate_composite_change_set(src_id, dst_id, app, composite); - L(F("calculated diff via direct analysis\n")); - } - else if (!(src_id == anc_id) && dst_id == anc_id) - { - change_set tmp; - calculate_composite_change_set(dst_id, src_id, app, tmp); - invert_change_set(tmp, m_new, composite); - L(F("calculated diff via inverted direct analysis\n")); - } - else - { - change_set anc_to_src, src_to_anc, anc_to_dst; - manifest_id anc_m_id; - manifest_map m_anc; + calculate_arbitrary_change_set(src_id, dst_id, app, composite); - I(!(src_id == anc_id || dst_id == anc_id)); - - app.db.get_revision_manifest(anc_id, anc_m_id); - app.db.get_manifest(anc_m_id, m_anc); - - calculate_composite_change_set(anc_id, src_id, app, anc_to_src); - invert_change_set(anc_to_src, m_anc, src_to_anc); - calculate_composite_change_set(anc_id, dst_id, app, anc_to_dst); - concatenate_change_sets(src_to_anc, anc_to_dst, composite); - L(F("calculated diff via common ancestor %s\n") % anc_id); - } - if (!new_is_archived) { L(F("concatenating un-committed changeset to composite\n")); --- constants.cc +++ constants.cc @@ -44,8 +44,11 @@ // truncated. size_t const db_log_line_sz = 70; - // size in bytes of the database xdelta version reconstruction cache - size_t const db_version_cache_sz = 1 << 20; + // size in bytes of the database xdelta version reconstruction cache. + // the value of 7 MB was determined as the optimal point after timing + // various values with a pull of the monotone repository - it could + // be tweaked further. + size_t const db_version_cache_sz = 7 * (1 << 20); // size of a line of text in the log buffer, beyond which log lines will be // truncated. --- contrib/mtbrowse.sh +++ contrib/mtbrowse.sh @@ -1,10 +1,10 @@ #!/bin/sh # # File: mtbrowse.sh # Description: Text based browser for monotone source control. # url: http://www.venge.net/monotone/ # Licence: GPL -# Autor: Henry Nestler +# Author: Henry Nestler # # Simple text based browser for Monotone repositories, written as shell script. # Can select branch, revision. Views diff from revision, logs, certs and more. @@ -63,10 +63,20 @@ # Check filname for reading before MT fails. # Exit after --help or --version. # +# 2005/6/16 Version 0.1.8 address@hidden +# automate ancestors, toposort, complete revision and +# automate parents missing param --db (if no MT directory). +# Switch --depth/--last without error dialog. +# Bug: Select rev for multiple parents (from merge), remove "cat cat". +# Use Author, not Key. Add Branch and Changelog in selection. +# Selectable format for Date, Branch, Author, ChangeLog. Coloring author. +# Current marker is asterix before date/time. +# # Known Bugs / ToDo-List: # * For Monotone Version >0.19 s/--depth/--last/, remove the fallback +# * better make "sed -n -e '1p'" for merge two different branches. -VERSION="0.1.7" +VERSION="0.1.8" # Save users settings # Default values, can overwrite on .mtbrowserc @@ -84,14 +94,11 @@ # Don't VISUAL and PAGER to use internal viewer. PAGER="less" -# View date and keys in revision selection? (yes) -SHOW_KEYS="yes" - # 1=Certs Cached, 0=Clean at end (slow and save mode) CACHE="1" # T=Topsort revisions, D=Date sort (reverse topsort) -TOPSORT="D" +TOPSORT="T" # count of certs to get from DB, "0" for all CERTS_MAX="20" @@ -99,6 +106,21 @@ # Trim hash code HASH_TRIM="10" +# Format Date/Time +FORMAT_DATE="L" + +# Format Branch Full,Short,None +FORMAT_BRANCH="F" + +# Format author (strip domain from mail address) +FORMAT_AUTHOR="F" + +# Changelog format +FORMAT_LOG="F" + +# Author coloring? +FORMAT_COLOR="\\Z7\\Zb" + # "log --depth=n" was changed to "log --last=n", see # Author: address@hidden, Date: 2005-05-30T00:15:27 # Autodetect this and fallback for a while. @@ -209,44 +231,104 @@ # Add the date and user-key to the list of revisions fill_date_key() { - local in_file=$1 - local out_file=$2 - local short_hash date key + local in_file=$1 + local out_file=$2 + local short_hash dat bra aut log - rm -f $out_file - if [ "$SHOW_KEYS" = "yes" ] - then - # Read Key and Date value from certs - cat $in_file | \ - while read hash ; do - echo -n "." + rm -f $out_file + # Read Key and Date value from certs + cat $in_file | \ + while read hash ; do + echo -n "." - # Scanning for - # Key : address@hidden <<--- - # Sig : ok - # Name : date - # Value : 2005-05-31T22:29:50 <<--- + # Scanning for + # Key : address@hidden + # Sig : ok + # Name : date + # Value : 2005-05-31T22:29:50 <<--- - # Output - # 123456 "2005-05-31T22:29:50 address@hidden" + # Output + # 123456 "2005-05-31 22:29 address@hidden" - eval `monotone --db=$DB list certs $hash | \ - tail -n 6 | sed -n -r \ - -e 's/Key : ([^ address@hidden ]+)$/key=\1/p' \ - -e 's/Value : ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:]{8})$/date=\1/p'` - short_hash=`echo $hash | cut -c 1-$HASH_TRIM` - echo "$short_hash \"$date $key\"" >> $out_file - done + short_hash=`echo $hash | cut -c 1-$HASH_TRIM` + + # get all certs of revision + monotone --db=$DB list certs $hash > $TEMPFILE.c.tmp + + # Date format + case $FORMAT_DATE in + F) # 2005-12-31T23:59:59 + dat=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : date/,+1s/Value : (.+)$/ \1/p'` + ;; + L) # 2005-12-31 23:59 + dat=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : date/,+1s/Value : (.{10})T(.{5}).+$/ \1 \2/p'` + ;; + D) # 2005-12-31 + dat=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : date/,+1s/Value : (.+)T.+$/ \1/p'` + ;; + S) # 12-31 23:59 + dat=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : date/,+1s/Value : .{4}-(.+)T(.{5}).+$/ \1 \2/p'` + ;; + T) # 23:59:59 + dat=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : date/,+1s/Value : .{10}T(.+{8})$/ \1/p'` + ;; + esac + + # Branch format + case $FORMAT_BRANCH in + F) # full + bra=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : branch/,+1s/Value : (.+)$/ \1/p' | \ + sed -n -e '1p'` + ;; + S) # short + bra=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : branch/,+1s/Value : .*\.([^\.]+)$/ \1/p' | \ + sed -n -e '1p'` + ;; + esac + + # Author format + case $FORMAT_AUTHOR in + F) # full + aut=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : author/,+1s/Value : (.+)$/\1/p'` + ;; + S) # short + aut=`cat $TEMPFILE.c.tmp | sed -n -r -e \ + '/^Name : author/,+1s/Value : (.{1,10})address@hidden/\1/p'` + ;; + esac + + # Changelog format + case $FORMAT_LOG in + F) # full + log=`cat $TEMPFILE.c.tmp | sed -n -r -e "y/\"/'/" -e \ + '/^Name : changelog/,+1s/Value : (.+)$/ \1/p'` + ;; + S) # short + log=`cat $TEMPFILE.c.tmp | sed -n -r -e "y/\"/'/" -e \ + '/^Name : changelog/,+1s/Value : (.{1,20}).*$/ \1/p'` + ;; + esac + + # Coloring? + if [ -n "$FORMAT_COLOR" -a "$FORMAT_AUTHOR" != "N" ] + then + # Bug in dialog: Don't allow empty string after \\Zn + test -z "$log" && log=" " + echo "$short_hash \"$dat$bra $FORMAT_COLOR$aut\\Zn$log\"" \ + >> $out_file else - # Read only Date value from certs - cat $in_file | \ - while read hash ; do - echo -n "." - monotone --db=$DB list certs $hash | sed -n -r -e \ - "s/Value : ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:]{8})\$/$hash \"\1\"/p" \ - | tail -n 1 >> $out_file - done + echo "$short_hash \"$dat$bra $aut$log\"" >> $out_file fi + done + rm $TEMPFILE.c.tmp } @@ -268,6 +350,8 @@ exit 1 fi + SHORT_DB=`basename $DB` + # is Branch set, than can return if [ -n "$BRANCH" -a -n "$1" ] then @@ -281,8 +365,6 @@ unset BRANCH fi - SHORT_DB=`basename $DB` - OLD_BRANCH=$BRANCH # Get branches from DB @@ -335,7 +417,7 @@ then HEAD=`cat $TEMPFILE.heads | head -n 1` else - # List heads with autor and date. Select by user. + # List heads with author and date. Select by user. monotone --db=$DB heads --branch=$BRANCH \ | sed -n -r -e 's/^([^ ]+) ([^ ]+) ([^ ]+)$/\1 \"\2 \3\"/p' \ | xargs dialog --begin 1 2 --menu "Select head" 0 0 0 \ @@ -378,15 +460,18 @@ > $TEMPFILE.change.log then DEPTH_LAST="--depth" - dialog --title " ERROR " --msgbox \ - "Fallback to \"$DEPTH_LAST\" usage.\nPlease try again." 6 40 - else - do_pager $TEMPFILE.change.log + echo "Fallback to --depth usage." + + # Try again + monotone --db=$DB log $DEPTH_LAST=1 --revision=$REVISION \ + > $TEMPFILE.change.log || exit 200 fi + + do_pager $TEMPFILE.change.log ;; P) # DIFF parent - monotone automate parents $REVISION > $TEMPFILE.parents + monotone --db=$DB automate parents $REVISION > $TEMPFILE.parents if [ `wc -l < $TEMPFILE.parents` -ne 1 ] then @@ -395,8 +480,9 @@ # Set DATE/KEY information fill_date_key $TEMPFILE.parents $TEMPFILE.certs3tmp - cat cat $TEMPFILE.certs3tmp | \ - xargs dialog --begin 1 2 --default-item "$PARENT" \ + cat $TEMPFILE.certs3tmp | \ + xargs dialog --begin 1 2 --colors \ + --default-item "$PARENT" \ --menu "Select parent for $REVISION" 0 0 0 \ 2> $TEMPFILE.input \ && PARENT=`cat $TEMPFILE.input` @@ -494,13 +580,13 @@ then echo "Reading ancestors ($HEAD)" echo "$HEAD" > $TEMPFILE.ancestors - monotone automate ancestors $HEAD | cut -c 1-40 \ + monotone --db=$DB automate ancestors $HEAD | cut -c 1-40 \ >> $TEMPFILE.ancestors || exit 200 if [ "$TOPSORT" = "T" -o "$CERTS_MAX" -gt 0 ] then echo "Topsort..." - monotone automate toposort `cat $TEMPFILE.ancestors` \ + monotone --db=$DB automate toposort `cat $TEMPFILE.ancestors` \ > $TEMPFILE.topsort || exit 200 if [ "$CERTS_MAX" -gt 0 ] @@ -534,6 +620,8 @@ while cat $TEMPFILE.certs.$BRANCH | \ xargs dialog \ --backtitle "h:$HEAD b:$BRANCH f:$SHORT_DB" \ + --no-shadow \ + --colors \ --default-item "$SHORT_REV" \ --menu "Select revision for branch:$BRANCH" \ 0 0 0 2> $TEMPFILE.revision-select @@ -543,16 +631,14 @@ # Remove old marker, set new marker cat $TEMPFILE.certs.$BRANCH | sed -r \ - -e "s/^(.+) <==\"\$/\1\"/" -e "s/^($SHORT_REV.+)\"\$/\1 <==\"/" \ + -e "s/^(.+\")\*(.+)\$/\1 \2/" \ + -e "s/^($SHORT_REV.* \") (.+)\$/\1\*\2/" \ > $TEMPFILE.certs.$BRANCH.base mv $TEMPFILE.certs.$BRANCH.base $TEMPFILE.certs.$BRANCH # Error, on "monotone automate parent XXXXXX", if short revision. :-( - # Expand revision here, if short revision - if [ "$SHOW_KEYS" = "yes" ] - then - REVISION=`monotone complete revision $SHORT_REV` - fi + # Expand revision here, if short revision (is alway short now) + REVISION=`monotone --db=$DB complete revision $SHORT_REV` # OK Button: Sub Menu do_action_sel @@ -564,15 +650,17 @@ # Menu for configuration do_config() { - local y n - while dialog --menu "Configuration" 0 0 0 \ "V" "VISUAL [$VISUAL]" \ "Vd" "Set VISUAL default to vim -R" \ "P" "PAGER [$PAGER]" \ "Pd" "set PAGER default to less" \ - "K" "View KEY in selection [$SHOW_KEYS]" \ "S" "Sort by Topsort or Date [$TOPSORT]" \ + "T" "Time and date format [$FORMAT_DATE]" \ + "B" "Branch format [$FORMAT_BRANCH]" \ + "A" "Author format [$FORMAT_AUTHOR]" \ + "Ac" "Author Color format [$FORMAT_COLOR]" \ + "L" "changeLog format [$FORMAT_LOG]" \ "C" "Certs limit in Select-List [$CERTS_MAX]" \ "-" "-" \ "W" "Write configuration file" \ @@ -602,35 +690,109 @@ # set Pager default PAGER="less" ;; - K) - # change yes=View Keys, no=date only - - if [ "$SHOW_KEYS" = "yes" ]; then - y="on" n="off" - else - y="off" n="on" - fi - - dialog --radiolist "View Keys in Selection?" 0 0 0 \ - "yes" "Short revision, date and keys" $y \ - "no" "Long revision and Date" $n \ - 2> $TEMPFILE.input \ - && SHOW_KEYS=`cat $TEMPFILE.input` - ;; S) # change T=Topsort revisions, D=Date sort (reverse topsort) - if [ "$TOPSORT" = "T" ]; then - y="on" n="off" - else - y="off" n="on" - fi - dialog --radiolist "Sort revisions by" 0 0 0 \ - "D" "Date/Time (reverse topsort)" $n \ - "T" "Topsort (from Monotone)" $y \ + "T" "Topsort, oldest top (from Monotone)" \ + `test "$TOPSORT" = "T" && echo "on" || echo "off"` \ + "D" "Date/Time (reverse topsort)" \ + `test "$TOPSORT" = "D" && echo "on" || echo "off"` \ 2> $TEMPFILE.input \ && TOPSORT=`cat $TEMPFILE.input` ;; + T) + # change date/time format + dialog --radiolist "Format for date" 0 0 0 \ + "F" "2005-12-31T23:59:59 -- Full date and time" \ + `test "$FORMAT_DATE" = "F" && echo "on" || echo "off"` \ + "L" "2005-12-31 23:59 -- Long date and time" \ + `test "$FORMAT_DATE" = "L" && echo "on" || echo "off"` \ + "D" "2005-21-31 -- Date only" \ + `test "$FORMAT_DATE" = "D" && echo "on" || echo "off"` \ + "S" "12-31 23:59:59 -- Short date and time" \ + `test "$FORMAT_DATE" = "S" && echo "on" || echo "off"` \ + "T" "23:59:59 -- Time only" \ + `test "$FORMAT_DATE" = "T" && echo "on" || echo "off"` \ + "N" "no date and no time" \ + `test "$FORMAT_DATE" = "N" && echo "on" || echo "off"` \ + 2> $TEMPFILE.input \ + && FORMAT_DATE=`cat $TEMPFILE.input` + ;; + B) + # change branch format + dialog --radiolist "Format for branch" 0 0 0 \ + "F" "Full author" \ + `test "$FORMAT_BRANCH" = "F" && echo "on" || echo "off"` \ + "S" "Short author, strip domain from email address" \ + `test "$FORMAT_BRANCH" = "S" && echo "on" || echo "off"` \ + "N" "no author" \ + `test "$FORMAT_BRANCH" = "N" && echo "on" || echo "off"` \ + 2> $TEMPFILE.input \ + && FORMAT_BRANCH=`cat $TEMPFILE.input` + ;; + A) + # change author's format + dialog --radiolist "Format for author" 0 0 0 \ + "F" "Full author" \ + `test "$FORMAT_AUTHOR" = "F" && echo "on" || echo "off"` \ + "S" "Short author, strip domain from email address" \ + `test "$FORMAT_AUTHOR" = "S" && echo "on" || echo "off"` \ + "N" "no author" \ + `test "$FORMAT_AUTHOR" = "N" && echo "on" || echo "off"` \ + 2> $TEMPFILE.input \ + && FORMAT_AUTHOR=`cat $TEMPFILE.input` + ;; + Ac) + # Author coloring + dialog --radiolist "Color author in selecetion" 0 0 0 \ + "yes" "author is color" \ + `test -n "$FORMAT_COLOR" && echo "on" || echo "off"` \ + "no" "author has no special color" \ + `test -z "$FORMAT_COLOR" && echo "on" || echo "off"` \ + 2> $TEMPFILE.input \ + && { + if [ "`cat $TEMPFILE.input`" = "yes" ] + then + dialog --colors \ + --default-item "$FORMAT_COLOR" \ + --menu "Selecet color for author" 0 0 0 \ + "\\Z0" "\Z0Color\Zn 0" \ + "\\Z1" "\Z1Color\Zn 1" \ + "\\Z2" "\Z2Color\Zn 2" \ + "\\Z3" "\Z3Color\Zn 3" \ + "\\Z4" "\Z4Color\Zn 4" \ + "\\Z5" "\Z5Color\Zn 5" \ + "\\Z6" "\Z6Color\Zn 6" \ + "\\Z7" "\Z7Color\Zn 7" \ + "\\Zb\\Z0" "\Zb\Z0Color\Zn 0b" \ + "\\Zb\\Z1" "\Zb\Z1Color\Zn 1b" \ + "\\Zb\\Z2" "\Zb\Z2Color\Zn 2b" \ + "\\Zb\\Z3" "\Zb\Z3Color\Zn 3b" \ + "\\Zb\\Z4" "\Zb\Z4Color\Zn 4b" \ + "\\Zb\\Z5" "\Zb\Z5Color\Zn 5b" \ + "\\Zb\\Z6" "\Zb\Z6Color\Zn 6b" \ + "\\Zb\\Z7" "\Zb\Z7Color\Zn 7b" \ + "\\Zb" "\ZbBold\Zn b" \ + "\\Zu" "\ZuUnderline\Zn u" \ + 2> $TEMPFILE.input \ + && FORMAT_COLOR=`cat $TEMPFILE.input` + else + FORMAT_COLOR="" + fi + } + ;; + L) + # Changelog format + dialog --radiolist "Format for ChangeLog in selcetion" 0 0 0 \ + "F" "Full changelog line" \ + `test "$FORMAT_LOG" = "F" && echo "on" || echo "off"` \ + "S" "Short changelog" \ + `test "$FORMAT_LOG" = "S" && echo "on" || echo "off"` \ + "N" "no changelog in selection" \ + `test "$FORMAT_LOG" = "N" && echo "on" || echo "off"` \ + 2> $TEMPFILE.input \ + && FORMAT_LOG=`cat $TEMPFILE.input` + ;; C) # Change CERTS_MAX dialog --inputbox \ @@ -649,11 +811,15 @@ PAGER="$PAGER" TEMPDIR="$TEMPDIR" TEMPFILE="$TEMPFILE" -SHOW_KEYS="$SHOW_KEYS" TOPSORT="$TOPSORT" CACHE="$CACHE" CERTS_MAX="$CERTS_MAX" DEPTH_LAST="$DEPTH_LAST" +FORMAT_DATE="$FORMAT_DATE" +FORMAT_BRANCH="$FORMAT_BRANCH" +FORMAT_AUTHOR="$FORMAT_AUTHOR" +FORMAT_LOG="$FORMAT_LOG" +FORMAT_COLOR="$FORMAT_COLOR" EOF dialog --title " Info " --sleep 2 --infobox \ "Configration wrote to\n$CONFIGFILE" 0 0 @@ -768,7 +934,8 @@ $DB -nt $TEMPFILE.changelog.$BRANCH ] then echo "Reading log...($BRANCH)" - monotone --db=$DB log --revision=$HEAD > $TEMPFILE.changelog.$BRANCH || exit 200 + monotone --db=$DB log --revision=$HEAD \ + > $TEMPFILE.changelog.$BRANCH || exit 200 fi cp $TEMPFILE.changelog.$BRANCH $TEMPFILE.change.log do_pager $TEMPFILE.change.log --- file_io.cc +++ file_io.cc @@ -384,7 +384,7 @@ if (!file) throw oops(string("cannot open file ") + p.string() + " for reading"); CryptoPP::FileSource f(file, true, new CryptoPP::StringSink(in)); - dat = in; + dat.swap(in); } // This function can only be called once per run. @@ -396,7 +396,7 @@ have_consumed_stdin = true; string in; CryptoPP::FileSource f(cin, true, new CryptoPP::StringSink(in)); - dat = in; + dat.swap(in); } void @@ -461,7 +461,7 @@ read_data(path, tdat); string tmp1, tmp2; - tmp2 = tdat(); + tdat.swap(tmp2); if (do_charconv) { tmp1 = tmp2; charset_convert(ext_charset, db_charset, tmp1, tmp2); @@ -470,7 +470,7 @@ tmp1 = tmp2; line_end_convert(db_linesep, tmp1, tmp2); } - dat = tmp2; + dat.swap(tmp2); } --- hmac.cc +++ hmac.cc @@ -0,0 +1,43 @@ +#include + +#include "cryptopp/hmac.h" +#include "cryptopp/sha.h" + +#include "sanity.hh" +#include "hmac.hh" +#include "vocab.hh" +#include "constants.hh" + +chained_hmac::chained_hmac(netsync_session_key const & session_key) : + key(session_key) +{ + memset(chain_val, 0, sizeof(chain_val)); +} + +void +chained_hmac::set_key(netsync_session_key const & session_key) +{ + key = session_key; +} + +std::string +chained_hmac::process(std::string const & str, size_t pos, size_t n) +{ + I(pos < str.size()); + if (n == std::string::npos) + n = str.size() - pos; + + I(pos + n <= str.size()); + + CryptoPP::HMAC + hmac(reinterpret_cast(key().data()), + constants::netsync_session_key_length_in_bytes); + hmac.Update(reinterpret_cast(chain_val), + sizeof(chain_val)); + hmac.Update(reinterpret_cast(str.data() + pos), + n); + hmac.Final(reinterpret_cast(chain_val)); + + std::string out(chain_val, sizeof(chain_val)); + return out; +} --- hmac.hh +++ hmac.hh @@ -0,0 +1,28 @@ +#ifndef __HMAC_HH__ +#define __HMAC_HH__ + +#include + +#include "cryptopp/hmac.h" +#include "cryptopp/sha.h" + +#include "vocab.hh" + +struct chained_hmac +{ + public: + chained_hmac(netsync_session_key const & session_key); + void set_key(netsync_session_key const & session_key); + std::string process(std::string const & str, size_t pos = 0, + size_t n = std::string::npos); + + private: + netsync_session_key key; + char chain_val[CryptoPP::SHA::DIGESTSIZE]; +}; + + + + +#endif // __HMAC_HH__ + --- netcmd.cc +++ netcmd.cc @@ -7,10 +7,6 @@ #include #include -#include "cryptopp/gzip.h" -#include "cryptopp/hmac.h" -#include "cryptopp/sha.h" - #include "adler32.hh" #include "constants.hh" #include "netcmd.hh" @@ -18,6 +14,7 @@ #include "numeric_vocab.hh" #include "sanity.hh" #include "transforms.hh" +#include "hmac.hh" using namespace std; using namespace boost; @@ -68,34 +65,19 @@ } void -netcmd::write(string & out, netsync_session_key const & key, - netsync_hmac_value & hmac_val) const +netcmd::write(string & out, chained_hmac & hmac) const { size_t oldlen = out.size(); out += static_cast(version); out += static_cast(cmd_code); insert_variable_length_string(payload, out); - I(key().size() == CryptoPP::SHA::DIGESTSIZE); - I(key().size() == hmac_val().size()); - byte keybuf[CryptoPP::SHA::DIGESTSIZE]; - for (size_t i = 0; i < sizeof(keybuf); i++) - { - keybuf[i] = key()[i] ^ hmac_val()[i]; - } - CryptoPP::HMAC hmac(keybuf, sizeof(keybuf)); - char digest[CryptoPP::SHA::DIGESTSIZE]; - hmac.CalculateDigest(reinterpret_cast(digest), - reinterpret_cast(out.data() + oldlen), - out.size() - oldlen); - string digest_str(digest, sizeof(digest)); - hmac_val = netsync_hmac_value(digest_str); - out.append(digest_str); + string digest = hmac.process(out, oldlen); + out.append(digest); } bool -netcmd::read(string & inbuf, netsync_session_key const & key, - netsync_hmac_value & hmac_val) +netcmd::read(string & inbuf, chained_hmac & hmac) { size_t pos = 0; @@ -142,15 +124,19 @@ throw bad_decode(F("oversized payload of '%d' bytes") % payload_len); // there might not be enough data yet in the input buffer - if (inbuf.size() < pos + payload_len + CryptoPP::SHA::DIGESTSIZE) + if (inbuf.size() < pos + payload_len + constants::netsync_hmac_value_length_in_bytes) { - inbuf.reserve(pos + payload_len + CryptoPP::SHA::DIGESTSIZE + constants::bufsz); + inbuf.reserve(pos + payload_len + constants::netsync_hmac_value_length_in_bytes + constants::bufsz); return false; } // out.payload = extract_substring(inbuf, pos, payload_len, "netcmd payload"); // Do this ourselves, so we can swap the strings instead of copying. require_bytes(inbuf, pos, payload_len, "netcmd payload"); + + // grab it before the data gets munged + string digest = hmac.process(inbuf, 0, pos + payload_len); + payload = inbuf.substr(pos + payload_len); inbuf.erase(pos + payload_len, inbuf.npos); inbuf.swap(payload); @@ -158,26 +144,13 @@ pos = 0; // they might have given us bogus data - string cmd_digest = extract_substring(inbuf, pos, CryptoPP::SHA::DIGESTSIZE, + string cmd_digest = extract_substring(inbuf, pos, + constants::netsync_hmac_value_length_in_bytes, "netcmd HMAC"); inbuf.erase(0, pos); - I(key().size() == CryptoPP::SHA::DIGESTSIZE); - I(key().size() == hmac_val().size()); - byte keybuf[CryptoPP::SHA::DIGESTSIZE]; - for (size_t i = 0; i < sizeof(keybuf); i++) - { - keybuf[i] = key()[i] ^ hmac_val()[i]; - } - CryptoPP::HMAC hmac(keybuf, sizeof(keybuf)); - char digest_buf[CryptoPP::SHA::DIGESTSIZE]; - hmac.CalculateDigest(reinterpret_cast(digest_buf), - reinterpret_cast(payload.data()), - payload.size()); - string digest(digest_buf, sizeof(digest_buf)); if (cmd_digest != digest) throw bad_decode(F("bad HMAC %s vs. %s") % encode_hexenc(cmd_digest) % encode_hexenc(digest)); - hmac_val = netsync_hmac_value(digest); payload.erase(0, payload_pos); return true; @@ -462,7 +435,13 @@ extract_variable_length_string(payload, dat, pos, "data netcmd, data payload"); if (compressed_p == 1) - dat = xform(dat); + { + gzip zdat; + data tdat; + zdat.swap(dat); + decode_gzip(zdat, tdat); + tdat.swap(dat); + } assert_end_of_buffer(payload, pos, "data netcmd payload"); } @@ -477,8 +456,10 @@ payload += item(); if (dat.size() > constants::netcmd_minimum_bytes_to_bother_with_gzip) { + gzip zdat; + encode_gzip(dat, zdat); string tmp; - tmp = xform(dat); + zdat.swap(tmp); payload += static_cast(1); // compressed flag insert_variable_length_string(tmp, payload); } @@ -510,8 +491,14 @@ extract_variable_length_string(payload, tmp, pos, "delta netcmd, delta payload"); if (compressed_p == 1) - tmp = xform(tmp); - del = delta(tmp); + { + gzip zdel(tmp); + decode_gzip(zdel, del); + } + else + { + del = tmp; + } assert_end_of_buffer(payload, pos, "delta netcmd payload"); } @@ -527,16 +514,19 @@ payload += base(); payload += ident(); - string tmp = del(); + string tmp; if (tmp.size() > constants::netcmd_minimum_bytes_to_bother_with_gzip) { payload += static_cast(1); // compressed flag - tmp = xform(tmp); + gzip zdel; + encode_gzip(del, zdel); + tmp = zdel(); } else { payload += static_cast(0); // compressed flag + tmp = del(); } I(tmp.size() <= constants::netcmd_payload_limit); insert_variable_length_string(tmp, payload); --- netcmd.hh +++ netcmd.hh @@ -12,6 +12,7 @@ #include "merkle_tree.hh" #include "numeric_vocab.hh" #include "vocab.hh" +#include "hmac.hh" typedef enum { @@ -63,10 +64,9 @@ // basic cmd i/o (including checksums) void write(std::string & out, - netsync_session_key const & key, - netsync_hmac_value & hmac_val) const; + chained_hmac & hmac) const; bool read(std::string & inbuf, - netsync_session_key const & key, netsync_hmac_value & hmac_val); + chained_hmac & hmac); // i/o functions for each type of command payload void read_error_cmd(std::string & errmsg) const; --- netsync.cc +++ netsync.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -32,6 +33,7 @@ #include "xdelta.hh" #include "epoch.hh" #include "platform.hh" +#include "hmac.hh" #include "globish.hh" #include "cryptopp/osrng.h" @@ -246,7 +248,12 @@ Netxx::Stream str; string inbuf; - string outbuf; + // deque of pair + deque< pair > outbuf; + // the total data stored in outbuf - this is + // used as a valve to stop too much data + // backing up + size_t outbuf_size; netcmd cmd; bool armed; @@ -255,8 +262,8 @@ id remote_peer_key_hash; rsa_keypair_id remote_peer_key_name; netsync_session_key session_key; - netsync_hmac_value read_hmac; - netsync_hmac_value write_hmac; + chained_hmac read_hmac; + chained_hmac write_hmac; bool authenticated; time_t last_io_time; @@ -306,6 +313,8 @@ id mk_nonce(); void mark_recent_io(); + void set_session_key(string const & key); + void setup_client_tickers(); bool done_all_refinements(); @@ -470,7 +479,7 @@ fd(sock), str(sock, to), inbuf(""), - outbuf(""), + outbuf_size(0), armed(false), remote_peer_key_hash(""), remote_peer_key_name(""), @@ -611,6 +620,14 @@ } void +session::set_session_key(string const & key) +{ + session_key = netsync_session_key(key); + read_hmac.set_key(session_key); + write_hmac.set_key(session_key); +} + +void session::setup_client_tickers() { byte_in_ticker.reset(new ticker("bytes in", ">", 1024, true)); @@ -759,7 +776,12 @@ session::write_netcmd_and_try_flush(netcmd const & cmd) { if (!encountered_error) - cmd.write(outbuf, session_key, write_hmac); + { + string buf; + cmd.write(buf, write_hmac); + outbuf.push_back(make_pair(buf, 0)); + outbuf_size += buf.size(); + } else L(F("dropping outgoing netcmd (because we're in error unwind mode)\n")); // FIXME: this helps keep the protocol pipeline full but it seems to @@ -1309,14 +1331,23 @@ session::write_some() { I(!outbuf.empty()); - Netxx::signed_size_type count = str.write(outbuf.data(), - std::min(outbuf.size(), + size_t writelen = outbuf.front().first.size() - outbuf.front().second; + Netxx::signed_size_type count = str.write(outbuf.front().first.data() + outbuf.front().second, + std::min(writelen, constants::bufsz)); if (count > 0) { - outbuf.erase(0, count); - L(F("wrote %d bytes to fd %d (peer %s), %d remain in output buffer\n") - % count % fd % peer_id % outbuf.size()); + if ((size_t)count == writelen) + { + outbuf_size -= outbuf.front().first.size(); + outbuf.pop_front(); + } + else + { + outbuf.front().second += count; + } + L(F("wrote %d bytes to fd %d (peer %s)\n") + % count % fd % peer_id); mark_recent_io(); if (byte_out_ticker.get() != NULL) (*byte_out_ticker) += count; @@ -1398,7 +1429,7 @@ cmd.write_anonymous_cmd(role, include_pattern, exclude_pattern, hmac_key_encrypted); write_netcmd_and_try_flush(cmd); - session_key = netsync_session_key(nonce2()); + set_session_key(nonce2()); } void @@ -1418,7 +1449,7 @@ cmd.write_auth_cmd(role, include_pattern, exclude_pattern, client, nonce1, hmac_key_encrypted, signature); write_netcmd_and_try_flush(cmd); - session_key = netsync_session_key(nonce2()); + set_session_key(nonce2()); } void @@ -1994,7 +2025,7 @@ load_priv_key(app, app.signing_key, our_priv); string hmac_key; decrypt_rsa(app.lua, app.signing_key, our_priv, hmac_key_encrypted, hmac_key); - session_key = netsync_session_key(hmac_key); + set_session_key(hmac_key); queue_confirm_cmd(); } @@ -3138,9 +3169,11 @@ { if (!armed) { - if (cmd.read(inbuf, session_key, read_hmac)) + if (outbuf_size > constants::bufsz * 10) + return false; // don't pack the buffer unnecessarily + + if (cmd.read(inbuf, read_hmac)) { -// inbuf.erase(0, cmd.encoded_size()); armed = true; } } --- revision.cc +++ revision.cc @@ -555,6 +555,12 @@ std::map< ctx, shared_bitmap > parents, ancestors; + if (left == right) + { + anc = left; + return true; + } + ctx ln = intern.intern(left.inner()()); ctx rn = intern.intern(right.inner()()); --- tests/t_diff_currev.at +++ tests/t_diff_currev.at @@ -1,9 +1,7 @@ # -*- Autoconf -*- AT_SETUP([diffing with explicit rev same as wc rev]) -AT_XFAIL_IF(true) - MONOTONE_SETUP AT_DATA(foo1, [foo file 1 --- transforms.cc +++ transforms.cc @@ -157,10 +157,43 @@ return n; } +template +void pack(T const & in, base64< gzip > & out) +{ + string tmp; + tmp.reserve(in().size()); // FIXME: do some benchmarking and make this a constant:: -// diffing and patching + CryptoPP::StringSource + str(in(), true, + new CryptoPP::Gzip( + new CryptoPP::Base64Encoder( + new CryptoPP::StringSink(tmp)))); + out.swap(tmp); +} +template +void unpack(base64< gzip > const & in, T & out) +{ + string tmp; + tmp.reserve(in().size()); // FIXME: do some benchmarking and make this a constant:: + CryptoPP::StringSource + str(in(), true, + new CryptoPP::Base64Decoder( + new CryptoPP::Gunzip( + new CryptoPP::StringSink(tmp)))); + + out.swap(tmp); +} + +// specialise them +template void pack(data const &, base64< gzip > &); +template void pack(delta const &, base64< gzip > &); +template void unpack(base64< gzip > const &, data &); +template void unpack(base64< gzip > const &, delta &); + +// diffing and patching + void diff(data const & olddata, data const & newdata, --- transforms.hh +++ transforms.hh @@ -73,24 +73,22 @@ void decode_gzip(gzip const & in, T & out) { out = xform(in()); } +// string variant for netsync +template +void encode_gzip(std::string const & in, gzip & out) +{ out = xform(in); } // both at once (this is relatively common) template -void pack(T const & in, base64< gzip > & out) -{ - gzip tmp; - encode_gzip(in, tmp); - encode_base64(tmp, out); -} +void pack(T const & in, base64< gzip > & out); +extern template void pack(data const &, base64< gzip > &); +extern template void pack(delta const &, base64< gzip > &); template -void unpack(base64< gzip > const & in, T & out) -{ - gzip tmp; - decode_base64(in, tmp); - decode_gzip(tmp, out); -} +void unpack(base64< gzip > const & in, T & out); +extern template void unpack(base64< gzip > const &, data &); +extern template void unpack(base64< gzip > const &, delta &); // diffing and patching --- vocab.hh +++ vocab.hh @@ -33,6 +33,8 @@ enc(std::string const & s); \ enc(INNER const & inner); \ enc(enc const & other); \ + void swap(std::string & str) \ + { i.swap(str); } \ std::string const & operator()() const \ { return i(); } \ bool operator<(enc const & x) const \ @@ -86,6 +88,8 @@ ty(ty const & other); \ std::string const & operator()() const \ { return s; } \ + void swap(std::string & str) \ + { s.swap(str); } \ bool operator<(ty const & other) const \ { return s < other(); } \ ty const & operator=(ty const & other); \