{"thread":{"id":"24638","subject":"What's cooking in git.git (Aug 2010, #01; Wed, 4)","startedAt":"2010-08-04T22:24:23Z","lastAt":"2010-08-06T05:44:23Z","messageCount":27,"participants":["Junio C Hamano","Ted Ts'o","Jonathan Nieder","Matthieu Moy","Tay Ray Chuan","Jakub Narebski","Jeff King","Jay Soffian","Dmitry V. Levin","Thomas Rast"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"147139","messageId":"7v62zqf23s.fsf@alter.siamese.dyndns.org","threadId":"24638","inReplyTo":null,"subject":"What's cooking in git.git (Aug 2010, #01; Wed, 4)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-04T22:24:23Z","receivedAt":"2010-08-04T22:24:23Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Here are the topics that have been cooking.  Commits prefixed with '-' are\nonly in 'pu' while commits prefixed with '+' are in 'next'.  The ones\nmarked with '.' do not appear in any of the integration branches, but I am\nstill holding onto them.\n\nThe tip of 'next' has been rewound and rebuilt on top of v1.7.2; also a\nfew topics have been ejected as I've been warning to.  I'll start merging\nmore stuff to 'next' in the next round after reading them over again.\n\n--------------------------------------------------\n[Graduated to \"master\"]\n\n* gp/pack-refs-remove-empty-dirs (2010-07-06) 1 commit\n  (merged to 'next' on 2010-07-14 at 7d25131)\n + pack-refs: remove newly empty directories\n\n* pt/git-gui (2010-08-02) 13 commits\n + Merge git://repo.or.cz/git-gui into pt/git-gui\n + git-gui: fix size and position of window panes on startup\n + git-gui: mc cannot be used before msgcat has been loaded\n + git-gui: use textconv filter for diff and blame\n + git-gui: Avoid using the <<Copy>> binding as a menu accelerator on win32\n + git-gui: fix shortcut creation on cygwin\n + git-gui: fix PATH environment for mingw development environment\n + git-gui: fix usage of _gitworktree when creating shortcut for windows\n + git-gui: fix \"Explore Working Copy\" for Windows again\n + git-gui: fix usage of themed widgets variable\n + git-gui: Handle failure of core.worktree to identify the working directory.\n + Merge branch 'maint'\n + git-gui: check whether systems nice command works or disable it\n\n* rr/svn-fe (2010-07-29) 2 commits\n + contrib/svn-fe: Add the svn-fe target to .gitignore\n + contrib/svn-fe: Fix IncludePath\n\n* sv/maint-diff-q-clear-fix (2010-08-02) 1 commit\n + Fix DIFF_QUEUE_CLEAR refactoring\n\n--------------------------------------------------\n[New Topics]\n\n* jc/sha1-name-find-fix (2010-08-02) 1 commit\n - sha1_name.c: fix parsing of \":/token\" syntax\n\n* jn/doc-pull (2010-08-02) 1 commit\n - Documentation: flesh out “git pull” description\n\n* jn/maint-gitweb-dynconf (2010-07-30) 1 commit\n - gitweb: allow configurations that change with each request\n\n* sr/local-config (2010-08-03) 1 commit\n - config: add --local option\n\n--------------------------------------------------\n[Stalled]\n\n* zl/mailinfo-recode-patch (2010-06-14) 2 commits\n - add --recode-patch option to git-am\n - add --recode-patch option to git-mailinfo\n\nI recall there was another round of re-roll planned for this one.\n\n* jk/tag-contains (2010-07-05) 4 commits\n - Why is \"git tag --contains\" so slow?\n - default core.clockskew variable to one day\n - limit \"contains\" traversals based on commit timestamp\n - tag: speed up --contains calculation\n\n--------------------------------------------------\n[Cooking]\n\n* ab/test-coverage (2010-07-26) 8 commits\n - Makefile: make gcov invocation configurable\n - t/README: Add a note about the dangers of coverage chasing\n - t/README: A new section about test coverage\n - Makefile: Add cover_db_html target\n - Makefile: Add cover_db target\n - Makefile: Split out the untested functions target\n - Makefile: Include subdirectories in \"make cover\" reports\n - gitignore: Ignore files generated by \"make coverage\"\n\n* ab/test-no-skip (2010-07-28) 5 commits\n - t/README: Update \"Skipping tests\" to align with best practices\n - t/t7800-difftool.sh: Skip with prereq on no PERL\n - t/t5800-remote-helpers.sh: Skip with prereq on python <2.4\n - t/t4004-diff-rename-symlink.sh: use three-arg <prereq>\n - tests: implicitly skip SYMLINKS tests using <prereq>\n\n* bc/use-more-hardlinks-in-install (2010-07-23) 2 commits\n - Makefile: make hard/symbolic links for non-builtins too\n - Makefile: link builtins residing in bin directory to main git binary too\n\n* cc/find-commit-subject (2010-07-22) 6 commits\n - blame: use find_commit_subject() instead of custom code\n - merge-recursive: use find_commit_subject() instead of custom code\n - bisect: use find_commit_subject() instead of custom code\n - revert: rename variables related to subject in get_message()\n - revert: refactor code to find commit subject in find_commit_subject()\n - revert: fix off by one read when searching the end of a commit subject\n\n* gb/shell-ext (2010-07-28) 3 commits\n - Add sample commands for git-shell\n - Add interactive mode to git-shell for user-friendliness\n - Allow creation of arbitrary git-shell commands\n\n* jc/log-grep (2010-07-19) 1 commit\n - git log: add -G<regexp> that greps in the patch text\n\n* jh/clean-exclude (2010-07-20) 2 commits\n - Add test for git clean -e.\n - Add -e/--exclude to git-clean.\n\n* jh/use-test-must-fail (2010-07-20) 1 commit\n - Convert \"! git\" to \"test_must_fail git\"\n\n* jn/apply-filename-with-sp (2010-07-23) 4 commits\n - apply: Handle traditional patches with space in filename\n - t4135 (apply): use expand instead of pr for portability\n - tests: Test how well \"git apply\" copes with weird filenames\n - apply: Split quoted filename handling into new function\n\n* jn/fix-abbrev (2010-07-27) 3 commits\n - examples/commit: use --abbrev for commit summary\n - checkout, commit: remove confusing assignments to rev.abbrev\n - archive: abbreviate substituted commit ids again\n\n* jn/maint-setup-fix (2010-07-24) 11 commits\n - setup: split off a function to handle ordinary .git directories\n - Revert \"rehabilitate 'git index-pack' inside the object store\"\n - setup: do not forget working dir from subdir of gitdir\n - t4111 (apply): refresh index before applying patches to it\n - setup: split off get_device_or_die helper\n - setup: split off a function to handle hitting ceiling in repo search\n - setup: split off code to handle stumbling upon a repository\n - setup: split off a function to checks working dir for .git file\n - setup: split off $GIT_DIR-set case from setup_git_directory_gently\n - tests: try git apply from subdir of toplevel\n - t1501 (rev-parse): clarify\n\n* jn/rebase-rename-am (2008-11-10) 5 commits\n - rebase: protect against diff.renames configuration\n - t3400 (rebase): whitespace cleanup\n - Teach \"apply --index-info\" to handle rename patches\n - t4150 (am): futureproof against failing tests\n - t4150 (am): style fix\n\n* ml/rebase-x-strategy (2010-07-29) 1 commit\n - rebase: support -X to pass through strategy options\n\n* mm/shortopt-detached (2010-07-30) 5 commits\n - log: parse detached option for --glob\n - log: parse detached options like git log --grep foo\n - diff: parse detached options --stat-width n, --stat-name-width n\n - diff: split off a function for --stat-* option parsing\n - diff: parse detached options like -S foo\n\n* nd/fix-sparse-checkout (2010-07-31) 5 commits\n - unpack-trees: mark new entries skip-worktree appropriately\n - unpack-trees: do not check for conflict entries too early\n - unpack-trees: let read-tree -u remove index entries outside sparse area\n - unpack-trees: only clear CE_UPDATE|CE_REMOVE when skip-worktree is always set\n - t1011 (sparse checkout): style nitpicks\n\n* tr/ab-i18n-fix (2010-07-25) 1 commit\n - tests: locate i18n lib&data correctly under --valgrind\n (this branch uses ab/i18n.)\n\n* tr/maint-no-unquote-plus (2010-07-24) 1 commit\n - Do not unquote + into ' ' in URLs\n\n* tr/xsize-bits (2010-07-28) 1 commit\n - xsize_t: check whether we lose bits\n\n* vs/doc-spell (2010-07-20) 1 commit\n - Documentation: spelling fixes\n\n* ab/report-corrupt-object-with-type (2010-06-10) 1 commit\n - sha1_file: Show the the type and path to corrupt objects\n\n* cc/revert (2010-07-21) 5 commits\n - t3508: add check_head_differs_from() helper function and use it\n - revert: improve success message by adding abbreviated commit sha1\n - revert: don't print \"Finished one cherry-pick.\" if commit failed\n - revert: refactor commit code into a new run_git_commit() function\n - revert: report success when using option --strategy\n\n* en/fast-export-fix (2010-07-17) 2 commits\n - fast-export: Add a --full-tree option\n - fast-export: Fix dropping of files with --import-marks and path limiting\n\n* jn/parse-date-basic (2010-07-15) 1 commit\n - Export parse_date_basic() to convert a date string to timestamp\n (this branch is used by rr/svn-export.)\n\n* kf/post-receive-sample-hook (2010-07-16) 1 commit\n - post-receive-email: optional message line count limit\n\n* tr/rfc-reset-doc (2010-07-18) 5 commits\n - Documentation/reset: move \"undo permanently\" example behind \"make topic\"\n - Documentation/reset: reorder examples to match description\n - Documentation/reset: promote 'examples' one section up\n - Documentation/reset: separate options by mode\n - Documentation/git-reset: reorder modes for soft-mixed-hard progression\n\n* rr/svn-export (2010-07-29) 9 commits\n - vcs-svn: Remove stray calls to removed functions\n - Add SVN dump parser\n - Add infrastructure to write revisions in fast-export format\n - Add stream helper library\n - Add string-specific memory pool\n - vcs-svn: treap_search should return NULL for missing items\n - Add treap implementation\n - Add memory pool library\n - Introduce vcs-svn lib\n (this branch uses jn/parse-date-basic.)\n\n* hv/autosquash-config (2010-07-14) 1 commit\n - add configuration variable for --autosquash option of interactive rebase\n\n* jh/graph-next-line (2010-07-13) 2 commits\n - Enable custom schemes for column colors in the graph API\n - Make graph_next_line() available in the graph.h API\n\n* ar/string-list-foreach (2010-07-03) 2 commits\n - Convert the users of for_each_string_list to for_each_string_list_item macro\n - Add a for_each_string_list_item macro\n (this branch is used by tf/string-list-init.)\n\n* il/rfc-remote-fd-ext (2010-07-31) 4 commits\n - Rewrite bidirectional traffic loop\n - gitignore: Ignore the new /git-remote-{ext,fd} helpers\n - New remote helper: git-remote-ext\n - New remote helper git-remote-fd\n\n* hv/submodule-find-ff-merge (2010-07-07) 3 commits\n - Implement automatic fast-forward merge for submodules\n - setup_revisions(): Allow walking history in a submodule\n - Teach ref iteration module about submodules\n\n* jn/fast-import-subtree (2010-06-30) 1 commit\n - Teach fast-import to import subtrees named by tree id\n\n* sg/rerere-gc-old-still-used (2010-07-13) 2 commits\n - rerere: fix overeager gc\n - mingw_utime(): handle NULL times parameter\n\n* tf/string-list-init (2010-07-04) 1 commit\n - string_list: Add STRING_LIST_INIT macro and make use of it.\n (this branch uses ar/string-list-foreach.)\n\n* en/d-f-conflict-fix (2010-07-27) 7 commits\n  (merged to 'next' on 2010-08-03 at 7f78604)\n + t/t6035-merge-dir-to-symlink.sh: Remove TODO on passing test\n + fast-import: Improve robustness when D->F changes provided in wrong order\n + fast-export: Fix output order of D/F changes\n + merge_recursive: Fix renames across paths below D/F conflicts\n + merge-recursive: Fix D/F conflicts\n + Add a rename + D/F conflict testcase\n + Add additional testcases for D/F conflicts\n\n* ab/i18n (2010-07-19) 2 commits\n - tests: rename test to work around GNU gettext bug\n - Add infrastructure for translating Git with gettext\n (this branch is used by tr/ab-i18n-fix.)\n\n* tc/checkout-B (2010-06-24) 3 commits\n - builtin/checkout: learn -B\n - builtin/checkout: reword hint for -b\n - add tests for checkout -b\n\n* eb/double-convert-before-merge (2010-07-02) 3 commits\n - Don't expand CRLFs when normalizing text during merge\n - Try normalizing files to avoid delete/modify conflicts when merging\n - Avoid conflicts when merging branches with mixed normalization\n"},{"id":"147146","messageId":"20100805001629.GC2901@thunk.org","threadId":"24638","inReplyTo":"7v62zqf23s.fsf@alter.siamese.dyndns.org","subject":"jk/tag-contains: stalled","fromName":"Ted Ts'o","fromEmail":"tytso@mit.edu","sentAt":"2010-08-05T00:16:29Z","receivedAt":"2010-08-05T00:16:29Z","isPatch":false,"sender":{"key":"tytso@mit.edu","avatar":"https://avatars.githubusercontent.com/u/51416?v=4"},"body":"On Wed, Aug 04, 2010 at 03:24:23PM -0700, Junio C Hamano wrote:\n> \n> * jk/tag-contains (2010-07-05) 4 commits\n>  - Why is \"git tag --contains\" so slow?\n>  - default core.clockskew variable to one day\n>  - limit \"contains\" traversals based on commit timestamp\n>  - tag: speed up --contains calculation\n\nWhat needs to be fixed up before this effort can graduate?  I find the\nfixups here to be really helpful, even without the automated skew\ndetection that has been proposed.  And even if we fix the root problem\nwith some new all-singing pack format, I suspect that may be a ways\nout, so it would be nice if these patches could get included for now....\n\n     \t   \t    \t    \t  \t  \t- Ted\n"},{"id":"147150","messageId":"20100805065312.GB5318@burratino","threadId":"24638","inReplyTo":"7v62zqf23s.fsf@alter.siamese.dyndns.org","subject":"tc/checkout-B","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-08-05T06:53:12Z","receivedAt":"2010-08-05T06:53:12Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Junio C Hamano wrote:\n\n> * tc/checkout-B (2010-06-24) 3 commits\n>  - builtin/checkout: learn -B\n>  - builtin/checkout: reword hint for -b\n>  - add tests for checkout -b\n\nI keep on trying to use this option and then remembering it wasn’t merged\nyet.  So for what it’s worth, I like it.\n"},{"id":"147152","messageId":"vpqmxt14gjt.fsf@bauges.imag.fr","threadId":"24638","inReplyTo":"7v62zqf23s.fsf@alter.siamese.dyndns.org","subject":"Re: What's cooking in git.git (Aug 2010, #01; Wed, 4)","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-05T08:20:06Z","receivedAt":"2010-08-05T08:20:06Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> * mm/shortopt-detached (2010-07-30) 5 commits\n>  - log: parse detached option for --glob\n>  - log: parse detached options like git log --grep foo\n>  - diff: parse detached options --stat-width n, --stat-name-width n\n>  - diff: split off a function for --stat-* option parsing\n>  - diff: parse detached options like -S foo\n\nI'm pretty sure I had send a new version of this one, but judging from\nthe mailing list's archive, I guess I mis-sent it and it never went\nthrough ;-).\n\nHere's a new one, with very minor revisions :\n\n* diff_long_opt renamed to parse_long_opt\n\n* Use the same wording as api-parse-options.txt : separate/sticked\n  forms (essentially in commit messages and comments).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"147157","messageId":"1280996576-1165-1-git-send-email-Matthieu.Moy@imag.fr","threadId":"24638","inReplyTo":"vpqmxt14gjt.fsf@bauges.imag.fr","subject":"[PATCH 1/5] diff: parse separate options like -S foo","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-05T08:22:52Z","receivedAt":"2010-08-05T08:22:52Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"Change the option parsing logic in revision.c to accept separate forms\nlike `-S foo' in addition to `-Sfoo'. The rest of git already accepted\nthis form, but revision.c still used its own option parsing.\n\nShort options affected are -S<string>, -l<num> and -O<orderfile>, for\nwhich an empty string wouldn't make sense, hence -<option> <arg> isn't\nambiguous.\n\nThis patch does not handle --stat-name-width and --stat-width, which are\nspecial-cases where diff_long_opt do not apply. They are handled in a\nseparate patch to ease review.\n\nOriginal patch by Matthieu Moy, plus refactoring by Jonathan Nieder.\n\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\n diff.c                       |   87 ++++++++++++++++++++++++++++++++++--------\n diff.h                       |    7 +++\n t/t4013-diff-various.sh      |    5 ++\n t/t4013/diff.log_-S_F_master |    7 +++\n t/t4202-log.sh               |   12 ++---\n 5 files changed, 95 insertions(+), 23 deletions(-)\n create mode 100644 t/t4013/diff.log_-S_F_master\n\ndiff --git a/diff.c b/diff.c\nindex 17873f3..bc8fa8e 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2990,9 +2990,50 @@ static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *va\n \n static int diff_scoreopt_parse(const char *opt);\n \n+static inline int short_opt(char opt, const char **argv,\n+\t\t\t    const char **optarg)\n+{\n+\tconst char *arg = argv[0];\n+\tif (arg[0] != '-' || arg[1] != opt)\n+\t\treturn 0;\n+\tif (arg[2] != '\\0') {\n+\t\t*optarg = arg + 2;\n+\t\treturn 1;\n+\t}\n+\tif (!argv[1])\n+\t\tdie(\"Option '%c' requires a value\", opt);\n+\t*optarg = argv[1];\n+\treturn 2;\n+}\n+\n+int parse_long_opt(const char *opt, const char **argv,\n+\t\t   const char **optarg)\n+{\n+\tconst char *arg = argv[0];\n+\tif (arg[0] != '-' || arg[1] != '-')\n+\t\treturn 0;\n+\targ += strlen(\"--\");\n+\tif (prefixcmp(arg, opt))\n+\t\treturn 0;\n+\targ += strlen(opt);\n+\tif (*arg == '=') { /* sticked form: --option=value */\n+\t\t*optarg = arg + 1;\n+\t\treturn 1;\n+\t}\n+\tif (*arg != '\\0')\n+\t\treturn 0;\n+\t/* separate form: --option value */\n+\tif (!argv[1])\n+\t\tdie(\"Option '--%s' requires a value\", opt);\n+\t*optarg = argv[1];\n+\treturn 2;\n+}\n+\n int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n {\n \tconst char *arg = av[0];\n+\tconst char *optarg;\n+\tint argcount;\n \n \t/* Output format options */\n \tif (!strcmp(arg, \"-p\") || !strcmp(arg, \"-u\") || !strcmp(arg, \"--patch\"))\n@@ -3149,10 +3190,11 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n \t\telse\n \t\t\tdie(\"bad --word-diff argument: %s\", type);\n \t}\n-\telse if (!prefixcmp(arg, \"--word-diff-regex=\")) {\n+\telse if ((argcount = parse_long_opt(\"word-diff-regex\", av, &optarg))) {\n \t\tif (options->word_diff == DIFF_WORDS_NONE)\n \t\t\toptions->word_diff = DIFF_WORDS_PLAIN;\n-\t\toptions->word_regex = arg + 18;\n+\t\toptions->word_regex = optarg;\n+\t\treturn argcount;\n \t}\n \telse if (!strcmp(arg, \"--exit-code\"))\n \t\tDIFF_OPT_SET(options, EXIT_WITH_STATUS);\n@@ -3180,18 +3222,26 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n \t/* misc options */\n \telse if (!strcmp(arg, \"-z\"))\n \t\toptions->line_termination = 0;\n-\telse if (!prefixcmp(arg, \"-l\"))\n-\t\toptions->rename_limit = strtoul(arg+2, NULL, 10);\n-\telse if (!prefixcmp(arg, \"-S\"))\n-\t\toptions->pickaxe = arg + 2;\n+\telse if ((argcount = short_opt('l', av, &optarg))) {\n+\t\toptions->rename_limit = strtoul(optarg, NULL, 10);\n+\t\treturn argcount;\n+\t}\n+\telse if ((argcount = short_opt('S', av, &optarg))) {\n+\t\toptions->pickaxe = optarg;\n+\t\treturn argcount;\n+\t}\n \telse if (!strcmp(arg, \"--pickaxe-all\"))\n \t\toptions->pickaxe_opts = DIFF_PICKAXE_ALL;\n \telse if (!strcmp(arg, \"--pickaxe-regex\"))\n \t\toptions->pickaxe_opts = DIFF_PICKAXE_REGEX;\n-\telse if (!prefixcmp(arg, \"-O\"))\n-\t\toptions->orderfile = arg + 2;\n-\telse if (!prefixcmp(arg, \"--diff-filter=\"))\n-\t\toptions->filter = arg + 14;\n+\telse if ((argcount = short_opt('O', av, &optarg))) {\n+\t\toptions->orderfile = optarg;\n+\t\treturn argcount;\n+\t}\n+\telse if ((argcount = parse_long_opt(\"diff-filter\", av, &optarg))) {\n+\t\toptions->filter = optarg;\n+\t\treturn argcount;\n+\t}\n \telse if (!strcmp(arg, \"--abbrev\"))\n \t\toptions->abbrev = DEFAULT_ABBREV;\n \telse if (!prefixcmp(arg, \"--abbrev=\")) {\n@@ -3201,20 +3251,25 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n \t\telse if (40 < options->abbrev)\n \t\t\toptions->abbrev = 40;\n \t}\n-\telse if (!prefixcmp(arg, \"--src-prefix=\"))\n-\t\toptions->a_prefix = arg + 13;\n-\telse if (!prefixcmp(arg, \"--dst-prefix=\"))\n-\t\toptions->b_prefix = arg + 13;\n+\telse if ((argcount = parse_long_opt(\"src-prefix\", av, &optarg))) {\n+\t\toptions->a_prefix = optarg;\n+\t\treturn argcount;\n+\t}\n+\telse if ((argcount = parse_long_opt(\"dst-prefix\", av, &optarg))) {\n+\t\toptions->b_prefix = optarg;\n+\t\treturn argcount;\n+\t}\n \telse if (!strcmp(arg, \"--no-prefix\"))\n \t\toptions->a_prefix = options->b_prefix = \"\";\n \telse if (opt_arg(arg, '\\0', \"inter-hunk-context\",\n \t\t\t &options->interhunkcontext))\n \t\t;\n-\telse if (!prefixcmp(arg, \"--output=\")) {\n-\t\toptions->file = fopen(arg + strlen(\"--output=\"), \"w\");\n+\telse if ((argcount = parse_long_opt(\"output\", av, &optarg))) {\n+\t\toptions->file = fopen(optarg, \"w\");\n \t\tif (!options->file)\n \t\t\tdie_errno(\"Could not open '%s'\", arg + strlen(\"--output=\"));\n \t\toptions->close_file = 1;\n+\t\treturn argcount;\n \t} else\n \t\treturn 0;\n \treturn 1;\ndiff --git a/diff.h b/diff.h\nindex 063d10a..2b94ad6 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -214,6 +214,13 @@ extern void diff_unmerge(struct diff_options *,\n #define DIFF_SETUP_USE_CACHE\t\t2\n #define DIFF_SETUP_USE_SIZE_CACHE\t4\n \n+/*\n+ * Poor man's alternative to parse-option, to allow both sticked form\n+ * (--option=value) and separate form (--option value).\n+ */\n+extern int parse_long_opt(const char *opt, const char **argv,\n+\t\t\t const char **optarg);\n+\n extern int git_diff_basic_config(const char *var, const char *value, void *cb);\n extern int git_diff_ui_config(const char *var, const char *value, void *cb);\n extern int diff_use_color_default;\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex dae6358..19857f4 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -208,6 +208,7 @@ log -p --first-parent master\n log -m -p --first-parent master\n log -m -p master\n log -SF master\n+log -S F master\n log -SF -p master\n log --decorate --all\n log --decorate=full --all\n@@ -282,4 +283,8 @@ diff master master^ side\n diff --dirstat master~1 master~2\n EOF\n \n+test_expect_success 'log -S requires an argument' '\n+\ttest_must_fail git log -S\n+'\n+\n test_done\ndiff --git a/t/t4013/diff.log_-S_F_master b/t/t4013/diff.log_-S_F_master\nnew file mode 100644\nindex 0000000..978d2b4\n--- /dev/null\n+++ b/t/t4013/diff.log_-S_F_master\n@@ -0,0 +1,7 @@\n+$ git log -S F master\n+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:02:00 2006 +0000\n+\n+    Third\n+$\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 2230e60..c1abd31 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -100,13 +100,11 @@ test_expect_success 'oneline' '\n \n test_expect_success 'diff-filter=A' '\n \n-\tactual=$(git log --pretty=\"format:%s\" --diff-filter=A HEAD) &&\n-\texpect=$(echo fifth ; echo fourth ; echo third ; echo initial) &&\n-\ttest \"$actual\" = \"$expect\" || {\n-\t\techo Oops\n-\t\techo \"Actual: $actual\"\n-\t\tfalse\n-\t}\n+\tgit log --pretty=\"format:%s\" --diff-filter=A HEAD > actual &&\n+\tgit log --pretty=\"format:%s\" --diff-filter A HEAD > actual-separate &&\n+\tprintf \"fifth\\nfourth\\nthird\\ninitial\" > expect &&\n+\ttest_cmp expect actual &&\n+\ttest_cmp expect actual-separate\n \n '\n \n-- \n1.7.2.1.30.g18195\n"},{"id":"147155","messageId":"1280996576-1165-2-git-send-email-Matthieu.Moy@imag.fr","threadId":"24638","inReplyTo":"vpqmxt14gjt.fsf@bauges.imag.fr","subject":"[PATCH 2/5] diff: split off a function for --stat-* option parsing","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-05T08:22:53Z","receivedAt":"2010-08-05T08:22:53Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"From: Jonathan Nieder <jrnieder@gmail.com>\n\nAs an optimization, the diff_opt_parse() switchboard has\na single case for all the --stat-* options.  Split it\noff into a separate function so we can enhance it\nwithout bringing code dangerously close to the right\nmargin.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\n diff.c |   62 +++++++++++++++++++++++++++++++++++---------------------------\n 1 files changed, 35 insertions(+), 27 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex bc8fa8e..a08a56a 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -3029,6 +3029,38 @@ int parse_long_opt(const char *opt, const char **argv,\n \treturn 2;\n }\n \n+static int stat_opt(struct diff_options *options, const char **av)\n+{\n+\tconst char *arg = av[0];\n+\tchar *end;\n+\tint width = options->stat_width;\n+\tint name_width = options->stat_name_width;\n+\n+\targ += strlen(\"--stat\");\n+\tend = (char *)arg;\n+\n+\tswitch (*arg) {\n+\tcase '-':\n+\t\tif (!prefixcmp(arg, \"-width=\"))\n+\t\t\twidth = strtoul(arg + 7, &end, 10);\n+\t\telse if (!prefixcmp(arg, \"-name-width=\"))\n+\t\t\tname_width = strtoul(arg + 12, &end, 10);\n+\t\tbreak;\n+\tcase '=':\n+\t\twidth = strtoul(arg+1, &end, 10);\n+\t\tif (*end == ',')\n+\t\t\tname_width = strtoul(end+1, &end, 10);\n+\t}\n+\n+\t/* Important! This checks all the error cases! */\n+\tif (*end)\n+\t\treturn 0;\n+\toptions->output_format |= DIFF_FORMAT_DIFFSTAT;\n+\toptions->stat_name_width = name_width;\n+\toptions->stat_width = width;\n+\treturn 1;\n+}\n+\n int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n {\n \tconst char *arg = av[0];\n@@ -3070,33 +3102,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n \t\toptions->output_format |= DIFF_FORMAT_NAME_STATUS;\n \telse if (!strcmp(arg, \"-s\"))\n \t\toptions->output_format |= DIFF_FORMAT_NO_OUTPUT;\n-\telse if (!prefixcmp(arg, \"--stat\")) {\n-\t\tchar *end;\n-\t\tint width = options->stat_width;\n-\t\tint name_width = options->stat_name_width;\n-\t\targ += 6;\n-\t\tend = (char *)arg;\n-\n-\t\tswitch (*arg) {\n-\t\tcase '-':\n-\t\t\tif (!prefixcmp(arg, \"-width=\"))\n-\t\t\t\twidth = strtoul(arg + 7, &end, 10);\n-\t\t\telse if (!prefixcmp(arg, \"-name-width=\"))\n-\t\t\t\tname_width = strtoul(arg + 12, &end, 10);\n-\t\t\tbreak;\n-\t\tcase '=':\n-\t\t\twidth = strtoul(arg+1, &end, 10);\n-\t\t\tif (*end == ',')\n-\t\t\t\tname_width = strtoul(end+1, &end, 10);\n-\t\t}\n-\n-\t\t/* Important! This checks all the error cases! */\n-\t\tif (*end)\n-\t\t\treturn 0;\n-\t\toptions->output_format |= DIFF_FORMAT_DIFFSTAT;\n-\t\toptions->stat_name_width = name_width;\n-\t\toptions->stat_width = width;\n-\t}\n+\telse if (!prefixcmp(arg, \"--stat\"))\n+\t\t/* --stat, --stat-width, or --stat-name-width */\n+\t\treturn stat_opt(options, av);\n \n \t/* renames options */\n \telse if (!prefixcmp(arg, \"-B\")) {\n-- \n1.7.2.1.30.g18195\n"},{"id":"147156","messageId":"1280996576-1165-3-git-send-email-Matthieu.Moy@imag.fr","threadId":"24638","inReplyTo":"vpqmxt14gjt.fsf@bauges.imag.fr","subject":"[PATCH 3/5] diff: parse separate options --stat-width n, --stat-name-width n","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-05T08:22:54Z","receivedAt":"2010-08-05T08:22:54Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"Part of a campaign for unstuck forms of options.\n\n[jn: with some refactoring]\n\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n diff.c |   28 +++++++++++++++++++++++-----\n 1 files changed, 23 insertions(+), 5 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex a08a56a..e98d59b 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -3035,16 +3035,34 @@ static int stat_opt(struct diff_options *options, const char **av)\n \tchar *end;\n \tint width = options->stat_width;\n \tint name_width = options->stat_name_width;\n+\tint argcount = 1;\n \n \targ += strlen(\"--stat\");\n \tend = (char *)arg;\n \n \tswitch (*arg) {\n \tcase '-':\n-\t\tif (!prefixcmp(arg, \"-width=\"))\n-\t\t\twidth = strtoul(arg + 7, &end, 10);\n-\t\telse if (!prefixcmp(arg, \"-name-width=\"))\n-\t\t\tname_width = strtoul(arg + 12, &end, 10);\n+\t\tif (!prefixcmp(arg, \"-width\")) {\n+\t\t\targ += strlen(\"-width\");\n+\t\t\tif (*arg == '=')\n+\t\t\t\twidth = strtoul(arg + 1, &end, 10);\n+\t\t\telse if (!*arg && !av[1])\n+\t\t\t\tdie(\"Option '--stat-width' requires a value\");\n+\t\t\telse if (!*arg) {\n+\t\t\t\twidth = strtoul(av[1], &end, 10);\n+\t\t\t\targcount = 2;\n+\t\t\t}\n+\t\t} else if (!prefixcmp(arg, \"-name-width\")) {\n+\t\t\targ += strlen(\"-name-width\");\n+\t\t\tif (*arg == '=')\n+\t\t\t\tname_width = strtoul(arg + 1, &end, 10);\n+\t\t\telse if (!*arg && !av[1])\n+\t\t\t\tdie(\"Option '--stat-name-width' requires a value\");\n+\t\t\telse if (!*arg) {\n+\t\t\t\tname_width = strtoul(av[1], &end, 10);\n+\t\t\t\targcount = 2;\n+\t\t\t}\n+\t\t}\n \t\tbreak;\n \tcase '=':\n \t\twidth = strtoul(arg+1, &end, 10);\n@@ -3058,7 +3076,7 @@ static int stat_opt(struct diff_options *options, const char **av)\n \toptions->output_format |= DIFF_FORMAT_DIFFSTAT;\n \toptions->stat_name_width = name_width;\n \toptions->stat_width = width;\n-\treturn 1;\n+\treturn argcount;\n }\n \n int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n-- \n1.7.2.1.30.g18195\n"},{"id":"147154","messageId":"1280996576-1165-4-git-send-email-Matthieu.Moy@imag.fr","threadId":"24638","inReplyTo":"vpqmxt14gjt.fsf@bauges.imag.fr","subject":"[PATCH 4/5] log: parse separate options like git log --grep foo","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-05T08:22:55Z","receivedAt":"2010-08-05T08:22:55Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\n revision.c     |   74 ++++++++++++++++++++++++++++++++++---------------------\n t/t4202-log.sh |    7 +++++\n 2 files changed, 53 insertions(+), 28 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 7e82efd..489a3c2 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1148,6 +1148,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\t\t       int *unkc, const char **unkv)\n {\n \tconst char *arg = argv[0];\n+\tconst char *optarg;\n+\tint argcount;\n \n \t/* pseudo revision arguments */\n \tif (!strcmp(arg, \"--all\") || !strcmp(arg, \"--branches\") ||\n@@ -1160,11 +1162,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\treturn 1;\n \t}\n \n-\tif (!prefixcmp(arg, \"--max-count=\")) {\n-\t\trevs->max_count = atoi(arg + 12);\n+\tif ((argcount = parse_long_opt(\"max-count\", argv, &optarg))) {\n+\t\trevs->max_count = atoi(optarg);\n \t\trevs->no_walk = 0;\n-\t} else if (!prefixcmp(arg, \"--skip=\")) {\n-\t\trevs->skip_count = atoi(arg + 7);\n+\t\treturn argcount;\n+\t} else if ((argcount = parse_long_opt(\"skip\", argv, &optarg))) {\n+\t\trevs->skip_count = atoi(optarg);\n+\t\treturn argcount;\n \t} else if ((*arg == '-') && isdigit(arg[1])) {\n \t/* accept -<digit>, like traditional \"head\" */\n \t\trevs->max_count = atoi(arg + 1);\n@@ -1178,18 +1182,24 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if (!prefixcmp(arg, \"-n\")) {\n \t\trevs->max_count = atoi(arg + 2);\n \t\trevs->no_walk = 0;\n-\t} else if (!prefixcmp(arg, \"--max-age=\")) {\n-\t\trevs->max_age = atoi(arg + 10);\n-\t} else if (!prefixcmp(arg, \"--since=\")) {\n-\t\trevs->max_age = approxidate(arg + 8);\n-\t} else if (!prefixcmp(arg, \"--after=\")) {\n-\t\trevs->max_age = approxidate(arg + 8);\n-\t} else if (!prefixcmp(arg, \"--min-age=\")) {\n-\t\trevs->min_age = atoi(arg + 10);\n-\t} else if (!prefixcmp(arg, \"--before=\")) {\n-\t\trevs->min_age = approxidate(arg + 9);\n-\t} else if (!prefixcmp(arg, \"--until=\")) {\n-\t\trevs->min_age = approxidate(arg + 8);\n+\t} else if ((argcount = parse_long_opt(\"max-age\", argv, &optarg))) {\n+\t\trevs->max_age = atoi(optarg);\n+\t\treturn argcount;\n+\t} else if ((argcount = parse_long_opt(\"since\", argv, &optarg))) {\n+\t\trevs->max_age = approxidate(optarg);\n+\t\treturn argcount;\n+\t} else if ((argcount = parse_long_opt(\"after\", argv, &optarg))) {\n+\t\trevs->max_age = approxidate(optarg);\n+\t\treturn argcount;\n+\t} else if ((argcount = parse_long_opt(\"min-age\", argv, &optarg))) {\n+\t\trevs->min_age = atoi(optarg);\n+\t\treturn argcount;\n+\t} else if ((argcount = parse_long_opt(\"before\", argv, &optarg))) {\n+\t\trevs->min_age = approxidate(optarg);\n+\t\treturn argcount;\n+\t} else if ((argcount = parse_long_opt(\"until\", argv, &optarg))) {\n+\t\trevs->min_age = approxidate(optarg);\n+\t\treturn argcount;\n \t} else if (!strcmp(arg, \"--first-parent\")) {\n \t\trevs->first_parent_only = 1;\n \t} else if (!strcmp(arg, \"--ancestry-path\")) {\n@@ -1295,6 +1305,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->pretty_given = 1;\n \t\tget_commit_format(arg+8, revs);\n \t} else if (!prefixcmp(arg, \"--pretty=\") || !prefixcmp(arg, \"--format=\")) {\n+\t\t/*\n+\t\t * Detached form (\"--pretty X\" as opposed to \"--pretty=X\")\n+\t\t * not allowed, since the argument is optional.\n+\t\t */\n \t\trevs->verbose_header = 1;\n \t\trevs->pretty_given = 1;\n \t\tget_commit_format(arg+9, revs);\n@@ -1359,21 +1373,25 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if (!strcmp(arg, \"--relative-date\")) {\n \t\trevs->date_mode = DATE_RELATIVE;\n \t\trevs->date_mode_explicit = 1;\n-\t} else if (!strncmp(arg, \"--date=\", 7)) {\n-\t\trevs->date_mode = parse_date_format(arg + 7);\n+\t} else if ((argcount = parse_long_opt(\"date\", argv, &optarg))) {\n+\t\trevs->date_mode = parse_date_format(optarg);\n \t\trevs->date_mode_explicit = 1;\n+\t\treturn argcount;\n \t} else if (!strcmp(arg, \"--log-size\")) {\n \t\trevs->show_log_size = 1;\n \t}\n \t/*\n \t * Grepping the commit log\n \t */\n-\telse if (!prefixcmp(arg, \"--author=\")) {\n-\t\tadd_header_grep(revs, GREP_HEADER_AUTHOR, arg+9);\n-\t} else if (!prefixcmp(arg, \"--committer=\")) {\n-\t\tadd_header_grep(revs, GREP_HEADER_COMMITTER, arg+12);\n-\t} else if (!prefixcmp(arg, \"--grep=\")) {\n-\t\tadd_message_grep(revs, arg+7);\n+\telse if ((argcount = parse_long_opt(\"author\", argv, &optarg))) {\n+\t\tadd_header_grep(revs, GREP_HEADER_AUTHOR, optarg);\n+\t\treturn argcount;\n+\t} else if ((argcount = parse_long_opt(\"committer\", argv, &optarg))) {\n+\t\tadd_header_grep(revs, GREP_HEADER_COMMITTER, optarg);\n+\t\treturn argcount;\n+\t} else if ((argcount = parse_long_opt(\"grep\", argv, &optarg))) {\n+\t\tadd_message_grep(revs, optarg);\n+\t\treturn argcount;\n \t} else if (!strcmp(arg, \"--extended-regexp\") || !strcmp(arg, \"-E\")) {\n \t\trevs->grep_filter.regflags |= REG_EXTENDED;\n \t} else if (!strcmp(arg, \"--regexp-ignore-case\") || !strcmp(arg, \"-i\")) {\n@@ -1382,12 +1400,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->grep_filter.fixed = 1;\n \t} else if (!strcmp(arg, \"--all-match\")) {\n \t\trevs->grep_filter.all_match = 1;\n-\t} else if (!prefixcmp(arg, \"--encoding=\")) {\n-\t\targ += 11;\n-\t\tif (strcmp(arg, \"none\"))\n-\t\t\tgit_log_output_encoding = xstrdup(arg);\n+\t} else if ((argcount = parse_long_opt(\"encoding\", argv, &optarg))) {\n+\t\tif (strcmp(optarg, \"none\"))\n+\t\t\tgit_log_output_encoding = xstrdup(optarg);\n \t\telse\n \t\t\tgit_log_output_encoding = \"\";\n+\t\treturn argcount;\n \t} else if (!strcmp(arg, \"--reverse\")) {\n \t\trevs->reverse ^= 1;\n \t} else if (!strcmp(arg, \"--children\")) {\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex c1abd31..95ac3f8 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -201,6 +201,13 @@ test_expect_success 'log --grep' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log --grep option parsing' '\n+\techo second >expect &&\n+\tgit log -1 --pretty=\"tformat:%s\" --grep sec >actual &&\n+\ttest_cmp expect actual &&\n+\ttest_must_fail git log -1 --pretty=\"tformat:%s\" --grep\n+'\n+\n test_expect_success 'log -i --grep' '\n \techo Second >expect &&\n \tgit log -1 --pretty=\"tformat:%s\" -i --grep=sec >actual &&\n-- \n1.7.2.1.30.g18195\n"},{"id":"147153","messageId":"1280996576-1165-5-git-send-email-Matthieu.Moy@imag.fr","threadId":"24638","inReplyTo":"vpqmxt14gjt.fsf@bauges.imag.fr","subject":"[PATCH 5/5] log: parse separate option for --glob","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-05T08:22:56Z","receivedAt":"2010-08-05T08:22:56Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\n revision.c               |    7 +++++--\n t/t6018-rev-list-glob.sh |    6 ++++++\n 2 files changed, 11 insertions(+), 2 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 489a3c2..f241f34 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1484,6 +1484,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n {\n \tint i, flags, left, seen_dashdash, read_from_stdin, got_rev_arg = 0;\n \tconst char **prune_data = NULL;\n+\tconst char *optarg;\n+\tint argcount;\n \n \t/* First, search for \"--\" */\n \tseen_dashdash = 0;\n@@ -1530,10 +1532,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \t\t\t\thandle_refs(revs, flags, for_each_remote_ref);\n \t\t\t\tcontinue;\n \t\t\t}\n-\t\t\tif (!prefixcmp(arg, \"--glob=\")) {\n+\t\t\tif ((argcount = parse_long_opt(\"glob\", argv + i, &optarg))) {\n \t\t\t\tstruct all_refs_cb cb;\n+\t\t\t\ti += argcount - 1;\n \t\t\t\tinit_all_refs_cb(&cb, revs, flags);\n-\t\t\t\tfor_each_glob_ref(handle_one_ref, arg + 7, &cb);\n+\t\t\t\tfor_each_glob_ref(handle_one_ref, optarg, &cb);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!prefixcmp(arg, \"--branches=\")) {\ndiff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh\nindex 58428d9..fb8291c 100755\n--- a/t/t6018-rev-list-glob.sh\n+++ b/t/t6018-rev-list-glob.sh\n@@ -123,6 +123,12 @@ test_expect_success 'rev-list --glob=refs/heads/subspace/*' '\n \n '\n \n+test_expect_success 'rev-list --glob refs/heads/subspace/*' '\n+\n+\tcompare rev-list \"subspace/one subspace/two\" \"--glob refs/heads/subspace/*\"\n+\n+'\n+\n test_expect_success 'rev-list --glob=heads/subspace/*' '\n \n \tcompare rev-list \"subspace/one subspace/two\" \"--glob=heads/subspace/*\"\n-- \n1.7.2.1.30.g18195\n"},{"id":"147163","messageId":"AANLkTi=P9cyKhQeFx4V0NsCRe7-cqEWiJMcWk0Tc=BOH@mail.gmail.com","threadId":"24638","inReplyTo":"20100805065312.GB5318@burratino","subject":"Re: tc/checkout-B","fromName":"Tay Ray Chuan","fromEmail":"rctay89@gmail.com","sentAt":"2010-08-05T10:18:55Z","receivedAt":"2010-08-05T10:18:55Z","isPatch":false,"sender":{"key":"rctay89@gmail.com","avatar":"https://avatars.githubusercontent.com/u/61553?v=4"},"body":"Hi,\n\nOn Thu, Aug 5, 2010 at 2:53 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n> Junio C Hamano wrote:\n>\n>> * tc/checkout-B (2010-06-24) 3 commits\n>>  - builtin/checkout: learn -B\n>>  - builtin/checkout: reword hint for -b\n>>  - add tests for checkout -b\n>\n> I keep on trying to use this option and then remembering it wasn’t merged\n> yet.  So for what it’s worth, I like it.\n\nThanks, glad to know this was useful to you.\n\n-- \nCheers,\nRay Chuan\n"},{"id":"147178","messageId":"20100805114132.GO13779@burratino","threadId":"24638","inReplyTo":"vpqmxt14gjt.fsf@bauges.imag.fr","subject":"mm/shortopt-detached","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-08-05T11:41:32Z","receivedAt":"2010-08-05T11:41:32Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Matthieu Moy wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n \n>> * mm/shortopt-detached (2010-07-30) 5 commits\n>>  - log: parse detached option for --glob\n>>  - log: parse detached options like git log --grep foo\n>>  - diff: parse detached options --stat-width n, --stat-name-width n\n>>  - diff: split off a function for --stat-* option parsing\n>>  - diff: parse detached options like -S foo\n[...]\n> Here's a new one, with very minor revisions :\n> \n> * diff_long_opt renamed to parse_long_opt\n> \n> * Use the same wording as api-parse-options.txt : separate/sticked\n>   forms (essentially in commit messages and comments).\n\nStill looks good to me.  Thanks.\n"},{"id":"147182","messageId":"m3zkx1ntkk.fsf@localhost.localdomain","threadId":"24638","inReplyTo":"1280996576-1165-1-git-send-email-Matthieu.Moy@imag.fr","subject":"Re: [PATCH 1/5] diff: parse separate options like -S foo","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-08-05T12:16:38Z","receivedAt":"2010-08-05T12:16:38Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Matthieu Moy <Matthieu.Moy@imag.fr> writes:\n\n> +static inline int short_opt(char opt, const char **argv,\n> +\t\t\t    const char **optarg)\n[...]\n> +int parse_long_opt(const char *opt, const char **argv,\n> +\t\t   const char **optarg)\n\nJust a nitpick question: why it is 'parse_long_opt' but just 'short_opt'?\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"147184","messageId":"vpqfwytxn6a.fsf@bauges.imag.fr","threadId":"24638","inReplyTo":"m3zkx1ntkk.fsf@localhost.localdomain","subject":"Re: [PATCH 1/5] diff: parse separate options like -S foo","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-05T12:24:13Z","receivedAt":"2010-08-05T12:24:13Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Matthieu Moy <Matthieu.Moy@imag.fr> writes:\n>\n>> +static inline int short_opt(char opt, const char **argv,\n>> +\t\t\t    const char **optarg)\n> [...]\n>> +int parse_long_opt(const char *opt, const char **argv,\n>> +\t\t   const char **optarg)\n>\n> Just a nitpick question: why it is 'parse_long_opt' but just\n> 'short_opt'?\n\nI initially made *_long_opt prefixed with something (diff_ in my first\nversion) because it's global, while short_opt is static.\nparse_short_opt is already taken in parse-option.c, so I'd rather\navoid re-using it (it's static there, so technically, we can,\nbut ...).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"147218","messageId":"7vsk2tdnv5.fsf@alter.siamese.dyndns.org","threadId":"24638","inReplyTo":"20100805001629.GC2901@thunk.org","subject":"Re: jk/tag-contains: stalled","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-05T16:29:34Z","receivedAt":"2010-08-05T16:29:34Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ted Ts'o <tytso@mit.edu> writes:\n\n> On Wed, Aug 04, 2010 at 03:24:23PM -0700, Junio C Hamano wrote:\n>> \n>> * jk/tag-contains (2010-07-05) 4 commits\n>>  - Why is \"git tag --contains\" so slow?\n>>  - default core.clockskew variable to one day\n>>  - limit \"contains\" traversals based on commit timestamp\n>>  - tag: speed up --contains calculation\n>\n> What needs to be fixed up before this effort can graduate?  I find the\n> fixups here to be really helpful, even without the automated skew\n> detection that has been proposed.  And even if we fix the root problem\n> with some new all-singing pack format, I suspect that may be a ways\n> out, so it would be nice if these patches could get included for now....\n\nI agree in principle; the log messages need to be cleaned up first\nat the least, though.\n"},{"id":"147225","messageId":"7vhbj9dm6h.fsf@alter.siamese.dyndns.org","threadId":"24638","inReplyTo":"7vsk2tdnv5.fsf@alter.siamese.dyndns.org","subject":"Re: jk/tag-contains: stalled","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-05T17:05:58Z","receivedAt":"2010-08-05T17:05:58Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Ted Ts'o <tytso@mit.edu> writes:\n>\n>> On Wed, Aug 04, 2010 at 03:24:23PM -0700, Junio C Hamano wrote:\n>>> \n>>> * jk/tag-contains (2010-07-05) 4 commits\n>>>  - Why is \"git tag --contains\" so slow?\n>>>  - default core.clockskew variable to one day\n>>>  - limit \"contains\" traversals based on commit timestamp\n>>>  - tag: speed up --contains calculation\n>>\n>> What needs to be fixed up before this effort can graduate?  I find the\n>> fixups here to be really helpful, even without the automated skew\n>> detection that has been proposed.  And even if we fix the root problem\n>> with some new all-singing pack format, I suspect that may be a ways\n>> out, so it would be nice if these patches could get included for now....\n>\n> I agree in principle; the log messages need to be cleaned up first\n> at the least, though.\n\nTo reduce the risk of double-work, I need to clarify.\n\nI meant to say that I can find enough material, especially what Peff\nwrote, in the discussion that followed in the thread to do the clean-up\nmyself.  No need to resend by anybody unless there are material\ndifferences from what have been discussed so far that need to be\nincorporated in the final series.\n"},{"id":"147227","messageId":"20100805173635.GA15760@sigill","threadId":"24638","inReplyTo":"7vhbj9dm6h.fsf@alter.siamese.dyndns.org","subject":"Re: jk/tag-contains: stalled","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-08-05T17:36:36Z","receivedAt":"2010-08-05T17:36:36Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Aug 05, 2010 at 10:05:58AM -0700, Junio C Hamano wrote:\n\n> >>> * jk/tag-contains (2010-07-05) 4 commits\n> >>>  - Why is \"git tag --contains\" so slow?\n> >>>  - default core.clockskew variable to one day\n> >>>  - limit \"contains\" traversals based on commit timestamp\n> >>>  - tag: speed up --contains calculation\n> [...]\n> > I agree in principle; the log messages need to be cleaned up first\n> > at the least, though.\n> \n> To reduce the risk of double-work, I need to clarify.\n> \n> I meant to say that I can find enough material, especially what Peff\n> wrote, in the discussion that followed in the thread to do the clean-up\n> myself.  No need to resend by anybody unless there are material\n> differences from what have been discussed so far that need to be\n> incorporated in the final series.\n\nThe only bad log message should be the final one, which should be\ndropped anyway. I would recommend just merging the first two for now,\nand Ted can tweak his core.clockskew manually.\n\n-Peff\n"},{"id":"147233","messageId":"7vy6ckdhhu.fsf@alter.siamese.dyndns.org","threadId":"24638","inReplyTo":"20100805173635.GA15760@sigill","subject":"Re: jk/tag-contains: stalled","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-05T18:47:09Z","receivedAt":"2010-08-05T18:47:09Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Thu, Aug 05, 2010 at 10:05:58AM -0700, Junio C Hamano wrote:\n>\n>> >>> * jk/tag-contains (2010-07-05) 4 commits\n>> >>>  - Why is \"git tag --contains\" so slow?\n>> >>>  - default core.clockskew variable to one day\n>> >>>  - limit \"contains\" traversals based on commit timestamp\n>> >>>  - tag: speed up --contains calculation\n>> [...]\n>> > I agree in principle; the log messages need to be cleaned up first\n>> > at the least, though.\n>> \n>> To reduce the risk of double-work, I need to clarify.\n>> \n>> I meant to say that I can find enough material, especially what Peff\n>> wrote, in the discussion that followed in the thread to do the clean-up\n>> myself.  No need to resend by anybody unless there are material\n>> differences from what have been discussed so far that need to be\n>> incorporated in the final series.\n>\n> The only bad log message should be the final one, which should be\n> dropped anyway. I would recommend just merging the first two for now,\n> and Ted can tweak his core.clockskew manually.\n\nAfter re-reviewing the one that is queued, the use of TMP_MARK smelled\nsomewhat bad to me.  It is named TMP_ exactly because it is meant to be\nused in a closed callpath---you can use it but you are supposed to clean\nit before you return the control to the caller, so that the caller can\nrely on TMP_MARK absent from any objects.\n\nUse of UNINTERESTING is similarly not kosher if this were to be used in\nlarger context outside of \"do 'tags --contains' and exit\".  You noted\nthese two points in your original RFC patch.\n\nBesides, \"contains()\" is too generic a name to live in commit.h.\n\nMy gut feeling is that it is probably Ok if contains() and its recursive\nhelper are moved to builtin/tag.c and are made static, to make it clear\nthat this should not be reused outside the current context as a generic\n\"contains\" function.  It would probably help to have a comment at the end\nof list_tags() to say that TMP_MARK _ought_ to be cleaned before leaving\nthe function but we don't do that because we know it is the last function\nin the callchain before we exit.\n\nBy the way, I wonder why pop_most_recent_commit() with a commit_list,\nwhich is the usual revision traversal ingredient for doing something like\nthis, was not used in the patch, though.  Is it because depth-first was\nnecessary?\n"},{"id":"147235","messageId":"20100805190653.GA2942@sigill","threadId":"24638","inReplyTo":"7vy6ckdhhu.fsf@alter.siamese.dyndns.org","subject":"Re: jk/tag-contains: stalled","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-08-05T19:06:54Z","receivedAt":"2010-08-05T19:06:54Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Aug 05, 2010 at 11:47:09AM -0700, Junio C Hamano wrote:\n\n> > The only bad log message should be the final one, which should be\n> > dropped anyway. I would recommend just merging the first two for now,\n> > and Ted can tweak his core.clockskew manually.\n> \n> After re-reviewing the one that is queued, the use of TMP_MARK smelled\n> somewhat bad to me.  It is named TMP_ exactly because it is meant to be\n> used in a closed callpath---you can use it but you are supposed to clean\n> it before you return the control to the caller, so that the caller can\n> rely on TMP_MARK absent from any objects.\n> \n> Use of UNINTERESTING is similarly not kosher if this were to be used in\n> larger context outside of \"do 'tags --contains' and exit\".  You noted\n> these two points in your original RFC patch.\n\nOops, thanks, I had forgotten that the marks needed to be addressed.\nShould I be introducing new flags? We have 27 flag bits, but I would\nhate to waste 2 of them.\n\n> Besides, \"contains()\" is too generic a name to live in commit.h.\n\nI agree it's a pretty generic name. I was trying to make this as generic\nas possible, at least within the domain of commits, so it could be a\nfaster replacement for calls to is_descendant_of. Maybe commit_contains?\n\n> My gut feeling is that it is probably Ok if contains() and its\n> recursive helper are moved to builtin/tag.c and are made static, to\n> make it clear that this should not be reused outside the current\n> context as a generic \"contains\" function.  It would probably help to\n> have a comment at the end of list_tags() to say that TMP_MARK _ought_\n> to be cleaned before leaving the function but we don't do that because\n> we know it is the last function in the callchain before we exit.\n\nBut my intent was to have a generic contains function. I was planning on\napplying this to \"git branch --contains\", as well, but my initial\napproach wasn't really any faster than the current code (probably\nbecause the number of branches tends to be small compared to the number\nof tags).\n\nIn an ideal object-oriented world, the interface would be:\n\n  void contains_init(struct contains_context *c,\n                     struct commit_list *needles);\n  void contains_check(struct contains_context *c, struct commit *haystack);\n  void contains_free(struct contains_context *c);\n\nBut for memory use reasons, we don't get our own private copy of each\ncommit. We can drop the \"init\" and have a \"free\" or \"clear\" which clears\nmarks on the global commit objects. But you also _must_ use the same\nneedle list for each contains check, or you will get bogus results\n(since the marks are essentially partial cached answers).\n\nI guess we could do:\n\n  static struct commit_list *contains_needles;\n\n  void contains_init(struct commit_list *needles)\n  {\n          if (contains_needles)\n                  die(\"BUG: somebody else is already checking contains!\");\n          copy_commit_list(&contains_needles, needles);\n  }\n\n  void contains_check(struct commit *haystack)\n  {\n     /* like contains, but check against our static contains_needles */\n  }\n\n  void contains_clear(struct contains_context *c)\n  {\n          /* free contains_needles list, set it to NULL */\n          /* clear commit marks */\n  }\n\n> By the way, I wonder why pop_most_recent_commit() with a commit_list,\n> which is the usual revision traversal ingredient for doing something like\n> this, was not used in the patch, though.  Is it because depth-first was\n> necessary?\n\nYes, it is because of the depth-first nature. The intent is to mark\nwhole sections of the subgraph as \"does not contain\". If you can think\nof a clever way around that, I would be interested to hear it. The fact\nthat it is a DFS is why we can possibly perform worse than the current\ncode (we might follow the wrong branch of a merge all the way down to\nthe root before realizing the commit in question is on the other side).\n\n-Peff\n"},{"id":"147237","messageId":"AANLkTimzn05tvwY=uG6VP6PXDHwA=wS9ECuK_9eWKtSx@mail.gmail.com","threadId":"24638","inReplyTo":"20100805190653.GA2942@sigill","subject":"Re: jk/tag-contains: stalled","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2010-08-05T19:18:15Z","receivedAt":"2010-08-05T19:18:15Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Aug 5, 2010 at 3:06 PM, Jeff King <peff@peff.net> wrote:\n> I agree it's a pretty generic name. I was trying to make this as generic\n> as possible, at least within the domain of commits, so it could be a\n> faster replacement for calls to is_descendant_of. Maybe commit_contains?\n\nI'm going to side-track this slightly. I wonder why branch and tag\nhave --contains, but it is not more generically available via\nrev-list?  I needed it the other day and spent 5 minutes looking at\nwhat it would take before I ended up just calling merge-base in a loop\nfor the commits I wanted to check.\n\nj.\n"},{"id":"147238","messageId":"20100805192723.GA10435@sigill","threadId":"24638","inReplyTo":"AANLkTimzn05tvwY=uG6VP6PXDHwA=wS9ECuK_9eWKtSx@mail.gmail.com","subject":"Re: jk/tag-contains: stalled","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-08-05T19:27:23Z","receivedAt":"2010-08-05T19:27:23Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Aug 05, 2010 at 03:18:15PM -0400, Jay Soffian wrote:\n\n> On Thu, Aug 5, 2010 at 3:06 PM, Jeff King <peff@peff.net> wrote:\n> > I agree it's a pretty generic name. I was trying to make this as generic\n> > as possible, at least within the domain of commits, so it could be a\n> > faster replacement for calls to is_descendant_of. Maybe commit_contains?\n> \n> I'm going to side-track this slightly. I wonder why branch and tag\n> have --contains, but it is not more generically available via\n> rev-list?  I needed it the other day and spent 5 minutes looking at\n> what it would take before I ended up just calling merge-base in a loop\n> for the commits I wanted to check.\n\nI'm not sure rev-list makes the most sense. We already have \"show\ncommits in X, but not in Y\". But I gather you wanted \"from a list\n(U,V,W,X), print each that contains Y\". Which is not really a rev-list\nfunction anymore, as it is not about listing revisions, but rather about\ngrepping a list you've given it.\n\nSomething like \"git for-each-ref --contains\" seems more sensible to me,\nthough it is not as generic as we could make it (I cannot use an\narbitrary list of commits to the \"haystack\", but only ones that have\nrefs pointing to them).\n\n-Peff\n"},{"id":"147240","messageId":"AANLkTinX+wwOqaTVTxsdOhrZXzsXFw819aiND63-ChLG@mail.gmail.com","threadId":"24638","inReplyTo":"20100805192723.GA10435@sigill","subject":"Re: jk/tag-contains: stalled","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2010-08-05T20:00:18Z","receivedAt":"2010-08-05T20:00:18Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Aug 5, 2010 at 3:27 PM, Jeff King <peff@peff.net> wrote:\n> I'm not sure rev-list makes the most sense. We already have \"show\n> commits in X, but not in Y\". But I gather you wanted \"from a list\n> (U,V,W,X), print each that contains Y\".\n\nCorrect.\n\n> Which is not really a rev-list\n> function anymore, as it is not about listing revisions, but rather about\n> grepping a list you've given it.\n\nWell maybe, but rev-list will already take a list of revs on stdin and\nyou can give it --no-walk, so it has already been abused to do more\nthan strictly list revisions. And what do you call this?\n\n$ git rev-list --branches --no-walk --author=gitster\n\n:-)\n\n\n> Something like \"git for-each-ref --contains\" seems more sensible to me,\n> though it is not as generic as we could make it (I cannot use an\n> arbitrary list of commits to the \"haystack\", but only ones that have\n> refs pointing to them).\n\nSure, and if I wanted to do that, I could've just created a bunch of\ntemporary light-weight tags for those commits I was potentially\ninterested in and then used tag --contains. :-)\n\nSo I don't think rev-list is such a bad place after all.\n\nj.\n"},{"id":"147244","messageId":"20100805203633.GL2901@thunk.org","threadId":"24638","inReplyTo":"20100805190653.GA2942@sigill","subject":"Re: jk/tag-contains: stalled","fromName":"Ted Ts'o","fromEmail":"tytso@mit.edu","sentAt":"2010-08-05T20:36:33Z","receivedAt":"2010-08-05T20:36:33Z","isPatch":false,"sender":{"key":"tytso@mit.edu","avatar":"https://avatars.githubusercontent.com/u/51416?v=4"},"body":"On Thu, Aug 05, 2010 at 03:06:54PM -0400, Jeff King wrote:\n> But my intent was to have a generic contains function. I was planning on\n> applying this to \"git branch --contains\", as well, but my initial\n> approach wasn't really any faster than the current code (probably\n> because the number of branches tends to be small compared to the number\n> of tags).\n\nAt work we have some 100 topics branches per kernel revision, and I\nhave a repository with 332 branches in it at the moment.  So there may\nvery well be repo's where git branch --contains might be faster with\nyour approach.\n\n\t\t\t\t\t\t\t- Ted\n"},{"id":"147246","messageId":"7vd3twdbny.fsf@alter.siamese.dyndns.org","threadId":"24638","inReplyTo":"20100805190653.GA2942@sigill","subject":"Re: jk/tag-contains: stalled","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-05T20:53:05Z","receivedAt":"2010-08-05T20:53:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Oops, thanks, I had forgotten that the marks needed to be addressed.\n> Should I be introducing new flags? We have 27 flag bits, but I would\n> hate to waste 2 of them.\n\nIn the longer term it would be not just nice but necessary for us to come\nup with a scheme where different codepaths can \"allocate bits from object\nflags\", without having to fear stepping on each other's toes.  Some\npossible approaches off the top of my head are:\n\n - Extend \"struct object\" by another uint64_t to give it 64 more bits?\n   That would make the minimum object size from 24 bytes to 32 bytes and\n   during a pack-object session we would keep a lot of objects (not just\n   commits but trees and blobs) in core, so we probably would not want to\n   do this.\n\n - Extend \"struct commit\" by another uint32_t?  Currently a \"struct\n   commit\" is 72 bytes on x86_64 (there is an unfortunate 4-byte padding\n   gap between indegree and date), and 48 bytes on i386 and this would\n   enlarge the latter to 52 bytes (this comes free on 64-bit archs).\n\n   As we need a lot more bits on commits than on other objects\n   (e.g. left-right do not need to be placed on trees or blobs), this\n   approach might be more space efficient.\n\n - Use one bit in the current flags section to signal \"extended flag bits\n   present on this object\", and have a separate hashtable for minority\n   objects that have that bit set?  This would work only for flag bits\n   that are rarely used (otherwise the secondary hashtable will be full of\n   objects and per-object overhead will kill us).\n\n - Migrate some users of flag bits that only mark small miniroty of\n   commits to use dedicated hashtable to free their bits [*1*].  I don't\n   know if there are candidates for doing this offhand.  Just uttering it\n   as an idea.\n\nIndependent of this issue, I suspect that we might want to fold\nobject.used into the general set of flags---it is only used by fsck as far\nas I remember.\n\n[Footnote]\n\n*1* Also we would want to do something similar to the commit.util field so\nthat more than one utility libraries can attach their own stuff to each\ncommit.  It _might_ make sense to instead get rid of commit.util and\nmigrate the users to a separate \"one object hash per one type of info\",\nthough.  In any case it is a separate topic.\n"},{"id":"147251","messageId":"20100805211223.GA12207@wo.int.altlinux.org","threadId":"24638","inReplyTo":"7v62zqf23s.fsf@alter.siamese.dyndns.org","subject":"Re: jc/sha1-name-find-fix","fromName":"Dmitry V. Levin","fromEmail":"ldv@altlinux.org","sentAt":"2010-08-05T21:12:23Z","receivedAt":"2010-08-05T21:12:23Z","isPatch":false,"sender":{"key":"ldv@altlinux.org","avatar":"https://avatars.githubusercontent.com/u/5281408?v=4"},"body":"On Wed, Aug 04, 2010 at 03:24:23PM -0700, Junio C Hamano wrote:\n[...]\n> [New Topics]\n> \n> * jc/sha1-name-find-fix (2010-08-02) 1 commit\n>  - sha1_name.c: fix parsing of \":/token\" syntax\n\nThank you for the fix.  BTW, it applies to maint with no regressions.\n\n\n-- \nldv\n"},{"id":"147256","messageId":"201008052338.16668.trast@student.ethz.ch","threadId":"24638","inReplyTo":"7vd3twdbny.fsf@alter.siamese.dyndns.org","subject":"Re: jk/tag-contains: stalled","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2010-08-05T21:38:16Z","receivedAt":"2010-08-05T21:38:16Z","isPatch":false,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Junio C Hamano wrote:\n> *1* Also we would want to do something similar to the commit.util field so\n> that more than one utility libraries can attach their own stuff to each\n> commit.  It _might_ make sense to instead get rid of commit.util and\n> migrate the users to a separate \"one object hash per one type of info\",\n> though.  In any case it is a separate topic.\n\nI thought this already existed in decorate.c?\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"147261","messageId":"7v4of8d7u2.fsf@alter.siamese.dyndns.org","threadId":"24638","inReplyTo":"201008052338.16668.trast@student.ethz.ch","subject":"Re: jk/tag-contains: stalled","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-05T22:15:49Z","receivedAt":"2010-08-05T22:15:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> Junio C Hamano wrote:\n>> *1* Also we would want to do something similar to the commit.util field so\n>> that more than one utility libraries can attach their own stuff to each\n>> commit.  It _might_ make sense to instead get rid of commit.util and\n>> migrate the users to a separate \"one object hash per one type of info\",\n>> though.  In any case it is a separate topic.\n>\n> I thought this already existed in decorate.c?\n\nYes, the point is that there may be cases where it may be better to\nmigrate some current commit.util users to that API.\n"},{"id":"147297","messageId":"7vr5ic9txk.fsf@alter.siamese.dyndns.org","threadId":"24638","inReplyTo":"20100805190653.GA2942@sigill","subject":"Re: jk/tag-contains: stalled","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-06T05:44:23Z","receivedAt":"2010-08-06T05:44:23Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Thu, Aug 05, 2010 at 11:47:09AM -0700, Junio C Hamano wrote:\n>\n>> My gut feeling is that it is probably Ok if contains() and its\n>> recursive helper are moved to builtin/tag.c and are made static, to\n>> make it clear that this should not be reused outside the current\n>> context as a generic \"contains\" function.  It would probably help to\n>> have a comment at the end of list_tags() to say that TMP_MARK _ought_\n>> to be cleaned before leaving the function but we don't do that because\n>> we know it is the last function in the callchain before we exit.\n\nAfter thinking about this a bit more, I changed my mind.\n\nI think depth-first traversal from all tag tips, without running any\ntraversal from the wanted commit, has a serious downside.  What happens\nwhen you run \"git tag --contains master\" in a Linus tree after a major\nrelease but before he tags the -rc1 and closes the merge window?  Doesn't\nthe algorithm run all the way down to the root, only to say nothing?\nAdmittedly the traversal will visit each commit once (starting from\nv2.6.12 down to v2.6.12-rc2, then skipping v2.6.12-rc2 through v2.6.12-rc6\nbecause they are already seen and known not to contain the \"master\", then\nstarting from v2.6.13 down to v2.6.12, and so on), but visiting all the\ncommits down to root feels really wrong.\n\nI think the merge-base traversal is essential.  Suppose we have hundreds\nof commits with two tags 'T1' and 'T2':\n\n                                  o---T2        o---o---Y\n                                 /             /\n ---o---o---o---o---o---o---o---%---...---X---*---T1\n\nIf you are probing for 'X', traversing from all the tags until you hit a\nwanted commit will stop at a reasonable point (namely, 'X') if you are\nlucky and you started from 'T1' not 'T2', with your new algorithm.  If you\nare unlucky and started from 'T2', you will however traverse down to root\nfrom 'T2' which would be the bulk of the history.\n\nAlso, when you are probing for 'Y', you end up traversing all the way\ndown, whether you start from 'T1' or 'T2', don't you?\n\nYou can (and should) dig both from 'Y' and 'T1' and stop traversal at '*',\nas that commit is an ancestor of 'Y' and at that point you have proven\nthat any ancestor of that you will find by traversing further will not\nfind 'Y'.  Similarly for 'Y' and 'T2' pair, which should stop at '%'.\n\nAs the author of show-branch, I think I know one trick that may speed this\nup without compromising the worst case scenario.\n\nWe can run this traversal in parallel for many tags at once.  Use bit #0\nof object.flags for the wanted commit, and bit #1..bit #N for N tags (if\nyou have more tags than that fit in the flags word, you run the algorithm\nmultiple times, N tags at a time, clearing the flags after each round).\n\nThe parallel traversal will run, smudging the parent commit's flags with\nthose of the child, in the usual way.\n\nSuppose that you are probing for 'Y'.  You start traversal from 'Y', 'T1'\nand 'T2' (as two tags will fit comfortably in a single flags word).  When\nyou come to commit '%', you will notice that all the ancestors of that\ncommit are contained in the wanted commit and all the tags you are probing\nfor ('T1' and 'T2').  There is no point to go further than that point\nduring this round, as you know you will not find 'Y' by digging further\nfrom that point.\n\nIn general, when you find that a commit has both bit #0 and bit #i set,\nthat commit is known to be a common ancestor between 'Y' and 'Ti', so\nthere is no point going further from that point to see if 'Ti' contains\n'Y'---you know it doesn't.  So you can stop when you see bit 0..N are all\nset.  After traversing as many commits as possible this way, look at the\nbits 1..i that is given to 'Y'.  They represent the set of tags that\ncontain 'Y' (you will find only bit #0 is set on 'Y').\n\nSimilarly, if you are probing for 'X', start the traversal from 'X', 'T1'\nand 'T2'.  The traversal that begins at 'T1' will reach 'X' (so 'X' will\ninitially start with bit #0 set, but then when the traversal that started\nfrom 'T1' reaches it, its bit #1 gets set) eventually.  Because bit #2 is\nnot set at that point, you don't stop and keep traversing.\n\nYou may already have started marking 'X' and its parent with bit #0 with\nthe traversal you started at 'X', but when you reach 'X' from 'T1' again,\nyou will be changing bit #1; anytime you change the flag, you would push\nthe commit back to the stack and re-traverse it.  Eventually, you will\nsmudge '%' with all 3 bits (depending on clock skew, you might traverse a\nfew more levels of its parents) and you can stop.  The flag word on 'X'\nwill have bis #0 and #1 set, so you know 'T1' reaches it but 'T2' doesn't.\n\nTo optimize this further, you may want to take advantage of the fact that\ntags are not supposed to change, and have a cache that knows what tag is\ncontained in what other tag (e.g. if v1.0 is contained in v2.0, you do not\nhave to run the probe for v2.0 once you know the wanted commit is\nreachable from v1.0).  But that can come later, I think.\n\nBut I haven't thought things really through.  If I am lucky, I may be able\nto find time tomorrow during the day to try conjuring something out, but\nno promises...\n"}]}