* What's cooking in git.git (Jan 2009, #05; Wed, 21)
@ 2009-01-22 3:55 Junio C Hamano
2009-01-22 4:26 ` Jeff King
` (2 more replies)
0 siblings, 3 replies; 23+ messages in thread
From: Junio C Hamano @ 2009-01-22 3:55 UTC (permalink / raw)
To: git
Here are the topics that have been cooking. Commits prefixed with '-' are
only in 'pu' while commits prefixed with '+' are in 'next'. The ones
marked with '.' do not appear in any of the branches, but I am still
holding onto them.
The topics list the commits in reverse chronological order. The topics
meant to be merged to the maintenance series have "maint-" in their names.
----------------------------------------------------------------
[New Topics]
* js/valgrind (Wed Jan 21 02:36:40 2009 +0100) 2 commits
- valgrind: ignore ldso errors
- Add valgrind support in test scripts
Dscho seems to have some updates out of discussion with Peff.
----------------------------------------------------------------
[Stalled and may need help and prodding to go forward]
* jc/blame (Wed Jun 4 22:58:40 2008 -0700) 2 commits
+ blame: show "previous" information in --porcelain/--incremental
format
+ git-blame: refactor code to emit "porcelain format" output
This gives Porcelains (like gitweb) the information on the commit _before_
the one that the final blame is laid on, which should save them one
rev-parse to dig further. The line number in the "previous" information
may need refining, and sanity checking code for reference counting may
need to be resurrected before this can move forward.
* db/foreign-scm (Sun Jan 11 15:12:10 2009 -0500) 3 commits
- Support fetching from foreign VCSes
- Add specification of git-vcs helpers
- Add "vcs" config option in remotes
The "spec" did not seem quite well cooked yet, but in the longer term I
think something like this to allow interoperating with other SCMs as if
the other end is a native git repository is a very worthy goal.
----------------------------------------------------------------
[Actively cooking]
* sp/runtime-prefix (Sun Jan 18 13:00:15 2009 +0100) 7 commits
- Windows: Revert to default paths and convert them by
RUNTIME_PREFIX
- Compute prefix at runtime if RUNTIME_PREFIX is set
- Modify setup_path() to only add git_exec_path() to PATH
- Add calls to git_extract_argv0_path() in programs that call
git_config_*
- git_extract_argv0_path(): Move check for valid argv0 from caller
to callee
- Refactor git_set_argv0_path() to git_extract_argv0_path()
- Move computation of absolute paths from Makefile to runtime (in
preparation for RUNTIME_PREFIX)
We should move this to 'next' soon with J6t's blessing.
* lh/submodule-tree-traversal (Mon Jan 12 00:45:55 2009 +0100) 3 commits
+ builtin-ls-tree: enable traversal of submodules
+ archive.c: enable traversal of submodules
+ tree.c: add support for traversal of submodules
I think choosing the submodules to descend into by seeing if the commit
happens to be available is a horribly broken semantics; it needs to be
fixed before this can move to 'master'.
* jk/signal-cleanup (Sun Jan 11 06:36:49 2009 -0500) 3 commits
- pager: do wait_for_pager on signal death
- refactor signal handling for cleanup functions
- chain kill signals for cleanup functions
I think this can move to 'next', as Peff and J6t agreed on how to fix
things up as needed for Windows.
* ks/maint-mailinfo-folded (Tue Jan 13 01:21:04 2009 +0300) 5 commits
- mailinfo: tests for RFC2047 examples
- mailinfo: add explicit test for mails like '<a.u.thor@example.com>
(A U Thor)'
- mailinfo: more smarter removal of rfc822 comments from 'From'
+ mailinfo: 'From:' header should be unfold as well
+ mailinfo: correctly handle multiline 'Subject:' header
As far as I can see, the only remaining thing is a minor fix-up in the
"comment removal" one before we can move this fully to 'next'.
* js/notes (Tue Jan 13 20:57:16 2009 +0100) 6 commits
+ git-notes: fix printing of multi-line notes
+ notes: fix core.notesRef documentation
+ Add an expensive test for git-notes
+ Speed up git notes lookup
+ Add a script to edit/inspect notes
+ Introduce commit notes
It would be nice to hear a real world success story using the notes
mechanism before casting this design in stone.
* sc/gitweb-category (Fri Dec 12 00:45:12 2008 +0100) 3 commits
- gitweb: Optional grouping of projects by category
- gitweb: Split git_project_list_body in two functions
- gitweb: Modularized git_get_project_description to be more generic
Design discussion between Jakub and Sebastien continues.
----------------------------------------------------------------
[Graduated to "master"]
* jk/color-parse (Sat Jan 17 10:38:46 2009 -0500) 2 commits
+ expand --pretty=format color options
+ color: make it easier for non-config to parse color specs
* sb/hook-cleanup (Sat Jan 17 04:02:55 2009 +0100) 5 commits
+ run_hook(): allow more than 9 hook arguments
+ run_hook(): check the executability of the hook before filling
argv
+ api-run-command.txt: talk about run_hook()
+ Move run_hook() from builtin-commit.c into run-command.c (libgit)
+ checkout: don't crash on file checkout before running post-
checkout hook
* rs/ctype (Sat Jan 17 16:50:37 2009 +0100) 4 commits
+ Add is_regex_special()
+ Change NUL char handling of isspecial()
+ Reformat ctype.c
+ Add ctype test
* jf/am-failure-report (Sun Jan 18 19:34:31 2009 -0800) 2 commits
+ git-am: re-fix the diag message printing
+ git-am: Make it easier to see which patch failed
* sg/maint-gitdir-in-subdir (Fri Jan 16 16:37:33 2009 +0100) 1 commit
+ Fix gitdir detection when in subdir of gitdir
This has my "don't do the fullpath if you are directly inside .git"
squashed in, so it should be much safer.
* am/maint-push-doc (Sun Jan 18 15:36:58 2009 +0100) 4 commits
+ Documentation: avoid using undefined parameters
+ Documentation: mention branches rather than heads
+ Documentation: remove a redundant elaboration
+ Documentation: git push repository can also be a remote
* lt/maint-wrap-zlib (Wed Jan 7 19:54:47 2009 -0800) 1 commit
+ Wrap inflate and other zlib routines for better error reporting
Needs the "free our memory upon seeing Z_MEM_ERROR and try again" bits
extracted from Shawn's patch on top of this one.
* kb/am-directory (Wed Jan 14 16:29:59 2009 -0800) 2 commits
+ git-am: fix shell quoting
+ git-am: add --directory=<dir> option
This is "third-time-lucky, perhaps?" resurrection. I do not think I'd be
using this very often, but it originated from a real user request.
* jc/maint-format-patch-o-relative (Mon Jan 12 15:18:02 2009 -0800) 1 commit
+ Teach format-patch to handle output directory relative to cwd
----------------------------------------------------------------
[Will merge to "master" soon]
* kb/lstat-cache (Sun Jan 18 16:14:54 2009 +0100) 5 commits
+ lstat_cache(): introduce clear_lstat_cache() function
+ lstat_cache(): introduce invalidate_lstat_cache() function
+ lstat_cache(): introduce has_dirs_only_path() function
+ lstat_cache(): introduce has_symlink_or_noent_leading_path()
function
+ lstat_cache(): more cache effective symlink/directory detection
* tr/previous-branch (Wed Jan 21 00:37:38 2009 -0800) 10 commits
+ Simplify parsing branch switching events in reflog
+ Introduce for_each_recent_reflog_ent().
+ interpret_nth_last_branch(): plug small memleak
+ Fix reflog parsing for a malformed branch switching entry
+ Fix parsing of @{-1}@{1}
+ interpret_nth_last_branch(): avoid traversing the reflog twice
+ checkout: implement "-" abbreviation, add docs and tests
+ sha1_name: support @{-N} syntax in get_sha1()
+ sha1_name: tweak @{-N} lookup
+ checkout: implement "@{-N}" shortcut name for N-th last branch
* js/maint-all-implies-HEAD (Sat Jan 17 22:27:08 2009 -0800) 2 commits
+ bundle: allow the same ref to be given more than once
+ revision walker: include a detached HEAD in --all
* mh/unify-color (Sun Jan 18 21:39:12 2009 +0100) 2 commits
+ move the color variables to color.c
+ handle color.ui at a central place
* cb/add-pathspec (Wed Jan 14 15:54:35 2009 +0100) 2 commits
+ remove pathspec_match, use match_pathspec instead
+ clean up pathspec matching
* js/diff-color-words (Tue Jan 20 21:46:57 2009 -0600) 8 commits
+ color-words: Support diff.wordregex config option
+ color-words: make regex configurable via attributes
+ color-words: expand docs with precise semantics
+ color-words: enable REG_NEWLINE to help user
+ color-words: take an optional regular expression describing words
+ color-words: change algorithm to allow for 0-character word
boundaries
+ color-words: refactor word splitting and use ALLOC_GROW()
+ Add color_fwrite_lines(), a function coloring each line
individually
* js/patience-diff (Thu Jan 1 17:39:37 2009 +0100) 3 commits
+ bash completions: Add the --patience option
+ Introduce the diff option '--patience'
+ Implement the patience diff algorithm
----------------------------------------------------------------
[On Hold]
* jk/renamelimit (Sat May 3 13:58:42 2008 -0700) 1 commit
. diff: enable "too large a rename" warning when -M/-C is explicitly
asked for
* jc/stripspace (Sun Mar 9 00:30:35 2008 -0800) 6 commits
. git-am --forge: add Signed-off-by: line for the author
. git-am: clean-up Signed-off-by: lines
. stripspace: add --log-clean option to clean up signed-off-by:
lines
. stripspace: use parse_options()
. Add "git am -s" test
. git-am: refactor code to add signed-off-by line for the committer
* jc/post-simplify (Fri Aug 15 01:34:51 2008 -0700) 2 commits
. revision --simplify-merges: incremental simplification
. revision --simplify-merges: prepare for incremental simplification
* wp/add-patch-find (Thu Nov 27 04:08:03 2008 +0000) 3 commits
. In add --patch, Handle K,k,J,j slightly more gracefully.
. Add / command in add --patch
. git-add -i/-p: Change prompt separater from slash to comma
* jc/grafts (Wed Jul 2 17:14:12 2008 -0700) 1 commit
. [BROKEN wrt shallow clones] Ignore graft during object transfer
* jc/replace (Fri Oct 31 09:21:39 2008 -0700) 1 commit
. WIP
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)
2009-01-22 3:55 What's cooking in git.git (Jan 2009, #05; Wed, 21) Junio C Hamano
@ 2009-01-22 4:26 ` Jeff King
2009-01-22 5:57 ` [PATCH v2 1/5] Windows: Fix signal numbers Jeff King
` (4 more replies)
2009-01-22 5:13 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Johannes Schindelin
2009-01-22 5:21 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Boyd Stephen Smith Jr.
2 siblings, 5 replies; 23+ messages in thread
From: Jeff King @ 2009-01-22 4:26 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Wed, Jan 21, 2009 at 07:55:36PM -0800, Junio C Hamano wrote:
> * jk/signal-cleanup (Sun Jan 11 06:36:49 2009 -0500) 3 commits
> - pager: do wait_for_pager on signal death
> - refactor signal handling for cleanup functions
> - chain kill signals for cleanup functions
>
> I think this can move to 'next', as Peff and J6t agreed on how to fix
> things up as needed for Windows.
Please wait for my re-roll, which I'll send in a few minutes.
-Peff
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)
2009-01-22 3:55 What's cooking in git.git (Jan 2009, #05; Wed, 21) Junio C Hamano
2009-01-22 4:26 ` Jeff King
@ 2009-01-22 5:13 ` Johannes Schindelin
2009-01-31 6:45 ` Sam Vilain
2009-01-22 5:21 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Boyd Stephen Smith Jr.
2 siblings, 1 reply; 23+ messages in thread
From: Johannes Schindelin @ 2009-01-22 5:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Wed, 21 Jan 2009, Junio C Hamano wrote:
> * js/notes (Tue Jan 13 20:57:16 2009 +0100) 6 commits
> + git-notes: fix printing of multi-line notes
> + notes: fix core.notesRef documentation
> + Add an expensive test for git-notes
> + Speed up git notes lookup
> + Add a script to edit/inspect notes
> + Introduce commit notes
>
> It would be nice to hear a real world success story using the notes
> mechanism before casting this design in stone.
I'd like to have some profiling done before that. For example, I am still
a bit unsure how the things would perform with a 50-deep delta chain for
a notes tree having 50,000+ notes in it (which I think will not be all
that unreasonable for a medium-sized project that stores bug-tracking
information in the notes).
I have a gut feeling that the performance dip I saw is a direct result of
doing away with the fan-out "subdirectories": remember, originally, I had
a tree structure much like the loose objects in .git/objects/??/, while
Peff convinced me that a flat tree object should be enough.
I could be wrong on that, though.
> * js/patience-diff (Thu Jan 1 17:39:37 2009 +0100) 3 commits
> + bash completions: Add the --patience option
> + Introduce the diff option '--patience'
> + Implement the patience diff algorithm
There is this one issue that my patience's output differs from bzr's.
Since the patience diff algorithm is so lousily documented, I do not know
if it is due to my misunderstanding the algorithm, or due to bzr doing
something clever in addition.
I'd be thankful if somebody could clarify that issue.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)
2009-01-22 3:55 What's cooking in git.git (Jan 2009, #05; Wed, 21) Junio C Hamano
2009-01-22 4:26 ` Jeff King
2009-01-22 5:13 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Johannes Schindelin
@ 2009-01-22 5:21 ` Boyd Stephen Smith Jr.
2009-01-23 6:23 ` Junio C Hamano
2009-01-27 1:43 ` Boyd Stephen Smith Jr.
2 siblings, 2 replies; 23+ messages in thread
From: Boyd Stephen Smith Jr. @ 2009-01-22 5:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
[-- Attachment #1: Type: text/plain, Size: 2008 bytes --]
On Wednesday 21 January 2009, Junio C Hamano <gitster@pobox.com> wrote
about 'What's cooking in git.git (Jan 2009, #05; Wed, 21)':
>* js/notes (Tue Jan 13 20:57:16 2009 +0100) 6 commits
> + git-notes: fix printing of multi-line notes
> + notes: fix core.notesRef documentation
> + Add an expensive test for git-notes
> + Speed up git notes lookup
> + Add a script to edit/inspect notes
> + Introduce commit notes
>
>It would be nice to hear a real world success story using the notes
>mechanism before casting this design in stone.
I'll see if I can't try to put this through some paces over the week.
Also, I'd like to see some support for notes in push/fetch, but it could
certainly be added afterwards.
>* js/diff-color-words (Tue Jan 20 21:46:57 2009 -0600) 8 commits
> + color-words: Support diff.wordregex config option
> + color-words: make regex configurable via attributes
> + color-words: expand docs with precise semantics
> + color-words: enable REG_NEWLINE to help user
> + color-words: take an optional regular expression describing words
> + color-words: change algorithm to allow for 0-character word
> boundaries
> + color-words: refactor word splitting and use ALLOC_GROW()
> + Add color_fwrite_lines(), a function coloring each line
> individually
I think my patch in
http://thread.gmane.org/gmane.comp.version-control.git/106567 should be
applied to the top of this. It respells "wordregex" to match existing
uses throughout the repo. Dscho had issues with one hunk, but I think I
addressed them in my follow-up. It looks like 98a4d87b (color-words:
Support diff.wordregex config option) still has the internally-consistent
runtogether spelling that doesn't match other configuration variables etc.
--
Boyd Stephen Smith Jr. ,= ,-_-. =.
bss@iguanasuicide.net ((_/)o o(\_))
ICQ: 514984 YM/AIM: DaTwinkDaddy `-'(. .)`-'
http://iguanasuicide.net/ \_/
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 1/5] Windows: Fix signal numbers
2009-01-22 4:26 ` Jeff King
@ 2009-01-22 5:57 ` Jeff King
2009-01-22 5:59 ` [PATCH v2 2/5] diff: refactor tempfile cleanup handling Jeff King
` (3 subsequent siblings)
4 siblings, 0 replies; 23+ messages in thread
From: Jeff King @ 2009-01-22 5:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
From: Johannes Sixt <j6t@kdbg.org>
We had defined some SIG_FOO macros that appear in the code, but that are
not supported on Windows, in order to make the code compile. But a
subsequent change will assert that a signal number is non-zero. We now
use the signal numbers that are commonly used on POSIX systems.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jeff King <peff@peff.net>
---
This is necessary to avoid violating sigchain assertions in the next
patch.
compat/mingw.h | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/compat/mingw.h b/compat/mingw.h
index 4f275cb..a255898 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -21,12 +21,12 @@ typedef int pid_t;
#define WEXITSTATUS(x) ((x) & 0xff)
#define WIFSIGNALED(x) ((unsigned)(x) > 259)
-#define SIGKILL 0
-#define SIGCHLD 0
-#define SIGPIPE 0
-#define SIGHUP 0
-#define SIGQUIT 0
-#define SIGALRM 100
+#define SIGHUP 1
+#define SIGQUIT 3
+#define SIGKILL 9
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGCHLD 17
#define F_GETFD 1
#define F_SETFD 2
--
1.6.1.403.g6c435
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 2/5] diff: refactor tempfile cleanup handling
2009-01-22 4:26 ` Jeff King
2009-01-22 5:57 ` [PATCH v2 1/5] Windows: Fix signal numbers Jeff King
@ 2009-01-22 5:59 ` Jeff King
2009-01-22 6:02 ` [PATCH v2 3/5] chain kill signals for cleanup functions Jeff King
` (2 subsequent siblings)
4 siblings, 0 replies; 23+ messages in thread
From: Jeff King @ 2009-01-22 5:59 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
There are two pieces of code that create tempfiles for diff:
run_external_diff and run_textconv. The former cleans up its
tempfiles in the face of premature death (i.e., by die() or
by signal), but the latter does not. After this patch, they
will both use the same cleanup routines.
To make clear what the change is, let me first explain what
happens now:
- run_external_diff uses a static global array of 2
diff_tempfile structs (since it knows it will always
need exactly 2 tempfiles). It calls prepare_temp_file
(which doesn't know anything about the global array) on
each of the structs, creating the tempfiles that need to
be cleaned up. It then registers atexit and signal
handlers to look through the global array and remove the
tempfiles. If it succeeds, it calls the handler manually
(which marks the tempfile structs as unused).
- textconv has its own tempfile struct, which it allocates
using prepare_temp_file and cleans up manually. No
signal or atexit handlers.
The new code moves the installation of cleanup handlers into
the prepare_temp_file function. Which means that that
function now has to understand that there is static tempfile
storage. So what happens now is:
- run_external_diff calls prepare_temp_file
- prepare_temp_file calls claim_diff_tempfile, which
allocates an unused slot from our global array
- prepare_temp_file installs (if they have not already
been installed) atexit and signal handlers for cleanup
- prepare_temp_file sets up the tempfile as usual
- prepare_temp_file returns a pointer to the allocated
tempfile
The advantage being that run_external_diff no longer has to
care about setting up cleanup handlers. Now by virtue of
calling prepare_temp_file, run_textconv gets the same
benefit, as will any future users of prepare_temp_file.
There are also a few side benefits to the specific
implementation:
- we now install cleanup handlers _before_ allocating the
tempfile, closing a race which could leave temp cruft
- when allocating a slot in the global array, we will now
detect a situation where the old slots were not properly
vacated (i.e., somebody forgot to call remove upon
leaving the function). In the old code, such a situation
would silently overwrite the tempfile names, meaning we
would forget to clean them up. The new code dies with a
bug warning.
- we make sure only to install the signal handler once.
This isn't a big deal, since we are just overwriting the
old handler, but will become an issue when a later patch
converts the code to use sigchain
Signed-off-by: Jeff King <peff@peff.net>
---
This patch is new since v1. I started with just looking at whether it
was safe to move the signal() call, but there were really several things
to be cleaned up, and it just made sense to do them all together.
diff.c | 107 +++++++++++++++++++++++++++++++++-------------------------------
1 files changed, 55 insertions(+), 52 deletions(-)
diff --git a/diff.c b/diff.c
index 0731313..ae6d552 100644
--- a/diff.c
+++ b/diff.c
@@ -167,6 +167,33 @@ static struct diff_tempfile {
char tmp_path[PATH_MAX];
} diff_temp[2];
+static struct diff_tempfile *claim_diff_tempfile(void) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
+ if (!diff_temp[i].name)
+ return diff_temp + i;
+ die("BUG: diff is failing to clean up its tempfiles");
+}
+
+static int remove_tempfile_installed;
+
+static void remove_tempfile(void)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
+ if (diff_temp[i].name == diff_temp[i].tmp_path) {
+ unlink(diff_temp[i].name);
+ diff_temp[i].name = NULL;
+ }
+}
+
+static void remove_tempfile_on_signal(int signo)
+{
+ remove_tempfile();
+ signal(SIGINT, SIG_DFL);
+ raise(signo);
+}
+
static int count_lines(const char *data, int size)
{
int count, ch, completely_empty = 1, nl_just_seen = 0;
@@ -1859,10 +1886,11 @@ static void prep_temp_blob(struct diff_tempfile *temp,
sprintf(temp->mode, "%06o", mode);
}
-static void prepare_temp_file(const char *name,
- struct diff_tempfile *temp,
- struct diff_filespec *one)
+static struct diff_tempfile *prepare_temp_file(const char *name,
+ struct diff_filespec *one)
{
+ struct diff_tempfile *temp = claim_diff_tempfile();
+
if (!DIFF_FILE_VALID(one)) {
not_a_valid_file:
/* A '-' entry produces this for file-2, and
@@ -1871,7 +1899,13 @@ static void prepare_temp_file(const char *name,
temp->name = "/dev/null";
strcpy(temp->hex, ".");
strcpy(temp->mode, ".");
- return;
+ return temp;
+ }
+
+ if (!remove_tempfile_installed) {
+ atexit(remove_tempfile);
+ signal(SIGINT, remove_tempfile_on_signal);
+ remove_tempfile_installed = 1;
}
if (!one->sha1_valid ||
@@ -1911,7 +1945,7 @@ static void prepare_temp_file(const char *name,
*/
sprintf(temp->mode, "%06o", one->mode);
}
- return;
+ return temp;
}
else {
if (diff_populate_filespec(one, 0))
@@ -1919,24 +1953,7 @@ static void prepare_temp_file(const char *name,
prep_temp_blob(temp, one->data, one->size,
one->sha1, one->mode);
}
-}
-
-static void remove_tempfile(void)
-{
- int i;
-
- for (i = 0; i < 2; i++)
- if (diff_temp[i].name == diff_temp[i].tmp_path) {
- unlink(diff_temp[i].name);
- diff_temp[i].name = NULL;
- }
-}
-
-static void remove_tempfile_on_signal(int signo)
-{
- remove_tempfile();
- signal(SIGINT, SIG_DFL);
- raise(signo);
+ return temp;
}
/* An external diff command takes:
@@ -1954,34 +1971,22 @@ static void run_external_diff(const char *pgm,
int complete_rewrite)
{
const char *spawn_arg[10];
- struct diff_tempfile *temp = diff_temp;
int retval;
- static int atexit_asked = 0;
- const char *othername;
const char **arg = &spawn_arg[0];
- othername = (other? other : name);
- if (one && two) {
- prepare_temp_file(name, &temp[0], one);
- prepare_temp_file(othername, &temp[1], two);
- if (! atexit_asked &&
- (temp[0].name == temp[0].tmp_path ||
- temp[1].name == temp[1].tmp_path)) {
- atexit_asked = 1;
- atexit(remove_tempfile);
- }
- signal(SIGINT, remove_tempfile_on_signal);
- }
-
if (one && two) {
+ struct diff_tempfile *temp_one, *temp_two;
+ const char *othername = (other ? other : name);
+ temp_one = prepare_temp_file(name, one);
+ temp_two = prepare_temp_file(othername, two);
*arg++ = pgm;
*arg++ = name;
- *arg++ = temp[0].name;
- *arg++ = temp[0].hex;
- *arg++ = temp[0].mode;
- *arg++ = temp[1].name;
- *arg++ = temp[1].hex;
- *arg++ = temp[1].mode;
+ *arg++ = temp_one->name;
+ *arg++ = temp_one->hex;
+ *arg++ = temp_one->mode;
+ *arg++ = temp_two->name;
+ *arg++ = temp_two->hex;
+ *arg++ = temp_two->mode;
if (other) {
*arg++ = other;
*arg++ = xfrm_msg;
@@ -3450,15 +3455,15 @@ void diff_unmerge(struct diff_options *options,
static char *run_textconv(const char *pgm, struct diff_filespec *spec,
size_t *outsize)
{
- struct diff_tempfile temp;
+ struct diff_tempfile *temp;
const char *argv[3];
const char **arg = argv;
struct child_process child;
struct strbuf buf = STRBUF_INIT;
- prepare_temp_file(spec->path, &temp, spec);
+ temp = prepare_temp_file(spec->path, spec);
*arg++ = pgm;
- *arg++ = temp.name;
+ *arg++ = temp->name;
*arg = NULL;
memset(&child, 0, sizeof(child));
@@ -3467,13 +3472,11 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
if (start_command(&child) != 0 ||
strbuf_read(&buf, child.out, 0) < 0 ||
finish_command(&child) != 0) {
- if (temp.name == temp.tmp_path)
- unlink(temp.name);
+ remove_tempfile();
error("error running textconv command '%s'", pgm);
return NULL;
}
- if (temp.name == temp.tmp_path)
- unlink(temp.name);
+ remove_tempfile();
return strbuf_detach(&buf, outsize);
}
--
1.6.1.403.g6c435
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 3/5] chain kill signals for cleanup functions
2009-01-22 4:26 ` Jeff King
2009-01-22 5:57 ` [PATCH v2 1/5] Windows: Fix signal numbers Jeff King
2009-01-22 5:59 ` [PATCH v2 2/5] diff: refactor tempfile cleanup handling Jeff King
@ 2009-01-22 6:02 ` Jeff King
2009-01-30 7:55 ` Jeff King
2009-01-22 6:03 ` [PATCH v2 4/5] refactor signal handling " Jeff King
2009-01-22 6:03 ` [PATCH v2 5/5] pager: do wait_for_pager on signal death Jeff King
4 siblings, 1 reply; 23+ messages in thread
From: Jeff King @ 2009-01-22 6:02 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
If a piece of code wanted to do some cleanup before exiting
(e.g., cleaning up a lockfile or a tempfile), our usual
strategy was to install a signal handler that did something
like this:
do_cleanup(); /* actual work */
signal(signo, SIG_DFL); /* restore previous behavior */
raise(signo); /* deliver signal, killing ourselves */
For a single handler, this works fine. However, if we want
to clean up two _different_ things, we run into a problem.
The most recently installed handler will run, but when it
removes itself as a handler, it doesn't put back the first
handler.
This patch introduces sigchain, a tiny library for handling
a stack of signal handlers. You sigchain_push each handler,
and use sigchain_pop to restore whoever was before you in
the stack.
Signed-off-by: Jeff King <peff@peff.net>
---
Two changes since last time:
- rebased on new 2/5, which fixes a problem the original had in calling
sigchain_push every time you did an external diff
- I tried to handle all systems in the test script, which should
hopefully now pass on Windows.
.gitignore | 1 +
Makefile | 3 +++
builtin-clone.c | 5 +++--
builtin-fetch--tool.c | 5 +++--
builtin-fetch.c | 5 +++--
diff.c | 5 +++--
http-push.c | 11 ++++++-----
lockfile.c | 13 +++++++------
sigchain.c | 43 +++++++++++++++++++++++++++++++++++++++++++
sigchain.h | 9 +++++++++
t/t0005-signals.sh | 22 ++++++++++++++++++++++
test-sigchain.c | 22 ++++++++++++++++++++++
12 files changed, 125 insertions(+), 19 deletions(-)
create mode 100644 sigchain.c
create mode 100644 sigchain.h
create mode 100755 t/t0005-signals.sh
create mode 100644 test-sigchain.c
diff --git a/.gitignore b/.gitignore
index d9adce5..f28a54d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -152,6 +152,7 @@ test-match-trees
test-parse-options
test-path-utils
test-sha1
+test-sigchain
common-cmds.h
*.tar.gz
*.dsc
diff --git a/Makefile b/Makefile
index 270b223..30371d1 100644
--- a/Makefile
+++ b/Makefile
@@ -388,6 +388,7 @@ LIB_H += revision.h
LIB_H += run-command.h
LIB_H += sha1-lookup.h
LIB_H += sideband.h
+LIB_H += sigchain.h
LIB_H += strbuf.h
LIB_H += tag.h
LIB_H += transport.h
@@ -481,6 +482,7 @@ LIB_OBJS += sha1-lookup.o
LIB_OBJS += sha1_name.o
LIB_OBJS += shallow.o
LIB_OBJS += sideband.o
+LIB_OBJS += sigchain.o
LIB_OBJS += strbuf.o
LIB_OBJS += symlinks.o
LIB_OBJS += tag.o
@@ -1365,6 +1367,7 @@ TEST_PROGRAMS += test-match-trees$X
TEST_PROGRAMS += test-parse-options$X
TEST_PROGRAMS += test-path-utils$X
TEST_PROGRAMS += test-sha1$X
+TEST_PROGRAMS += test-sigchain$X
all:: $(TEST_PROGRAMS)
diff --git a/builtin-clone.c b/builtin-clone.c
index f7e5a7b..849cefc 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -19,6 +19,7 @@
#include "strbuf.h"
#include "dir.h"
#include "pack-refs.h"
+#include "sigchain.h"
/*
* Overall FIXMEs:
@@ -288,7 +289,7 @@ static void remove_junk(void)
static void remove_junk_on_signal(int signo)
{
remove_junk();
- signal(SIGINT, SIG_DFL);
+ sigchain_pop(signo);
raise(signo);
}
@@ -441,7 +442,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
}
junk_git_dir = git_dir;
atexit(remove_junk);
- signal(SIGINT, remove_junk_on_signal);
+ sigchain_push(SIGINT, remove_junk_on_signal);
setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1);
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index 469b07e..b1d7f8f 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -2,6 +2,7 @@
#include "cache.h"
#include "refs.h"
#include "commit.h"
+#include "sigchain.h"
static char *get_stdin(void)
{
@@ -186,7 +187,7 @@ static void remove_keep(void)
static void remove_keep_on_signal(int signo)
{
remove_keep();
- signal(SIGINT, SIG_DFL);
+ sigchain_pop(signo);
raise(signo);
}
@@ -245,7 +246,7 @@ static int fetch_native_store(FILE *fp,
char buffer[1024];
int err = 0;
- signal(SIGINT, remove_keep_on_signal);
+ sigchain_push(SIGINT, remove_keep_on_signal);
atexit(remove_keep);
while (fgets(buffer, sizeof(buffer), stdin)) {
diff --git a/builtin-fetch.c b/builtin-fetch.c
index de6f307..8c86974 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -10,6 +10,7 @@
#include "transport.h"
#include "run-command.h"
#include "parse-options.h"
+#include "sigchain.h"
static const char * const builtin_fetch_usage[] = {
"git fetch [options] [<repository> <refspec>...]",
@@ -58,7 +59,7 @@ static void unlock_pack(void)
static void unlock_pack_on_signal(int signo)
{
unlock_pack();
- signal(SIGINT, SIG_DFL);
+ sigchain_pop(signo);
raise(signo);
}
@@ -672,7 +673,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
ref_nr = j;
}
- signal(SIGINT, unlock_pack_on_signal);
+ sigchain_push(SIGINT, unlock_pack_on_signal);
atexit(unlock_pack);
exit_code = do_fetch(transport,
parse_fetch_refspec(ref_nr, refs), ref_nr);
diff --git a/diff.c b/diff.c
index ae6d552..dacd5d2 100644
--- a/diff.c
+++ b/diff.c
@@ -12,6 +12,7 @@
#include "run-command.h"
#include "utf8.h"
#include "userdiff.h"
+#include "sigchain.h"
#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
@@ -190,7 +191,7 @@ static void remove_tempfile(void)
static void remove_tempfile_on_signal(int signo)
{
remove_tempfile();
- signal(SIGINT, SIG_DFL);
+ sigchain_pop(signo);
raise(signo);
}
@@ -1904,7 +1905,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
if (!remove_tempfile_installed) {
atexit(remove_tempfile);
- signal(SIGINT, remove_tempfile_on_signal);
+ sigchain_push(SIGINT, remove_tempfile_on_signal);
remove_tempfile_installed = 1;
}
diff --git a/http-push.c b/http-push.c
index cb5bf95..4c92f80 100644
--- a/http-push.c
+++ b/http-push.c
@@ -10,6 +10,7 @@
#include "exec_cmd.h"
#include "remote.h"
#include "list-objects.h"
+#include "sigchain.h"
#include <expat.h>
@@ -1364,7 +1365,7 @@ static void remove_locks(void)
static void remove_locks_on_signal(int signo)
{
remove_locks();
- signal(signo, SIG_DFL);
+ sigchain_pop(signo);
raise(signo);
}
@@ -2266,10 +2267,10 @@ int main(int argc, char **argv)
goto cleanup;
}
- signal(SIGINT, remove_locks_on_signal);
- signal(SIGHUP, remove_locks_on_signal);
- signal(SIGQUIT, remove_locks_on_signal);
- signal(SIGTERM, remove_locks_on_signal);
+ sigchain_push(SIGINT, remove_locks_on_signal);
+ sigchain_push(SIGHUP, remove_locks_on_signal);
+ sigchain_push(SIGQUIT, remove_locks_on_signal);
+ sigchain_push(SIGTERM, remove_locks_on_signal);
/* Check whether the remote has server info files */
remote->can_update_info_refs = 0;
diff --git a/lockfile.c b/lockfile.c
index 8589155..3cd57dc 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -2,6 +2,7 @@
* Copyright (c) 2005, Junio C Hamano
*/
#include "cache.h"
+#include "sigchain.h"
static struct lock_file *lock_file_list;
static const char *alternate_index_output;
@@ -24,7 +25,7 @@ static void remove_lock_file(void)
static void remove_lock_file_on_signal(int signo)
{
remove_lock_file();
- signal(signo, SIG_DFL);
+ sigchain_pop(signo);
raise(signo);
}
@@ -136,11 +137,11 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
if (0 <= lk->fd) {
if (!lock_file_list) {
- signal(SIGINT, remove_lock_file_on_signal);
- signal(SIGHUP, remove_lock_file_on_signal);
- signal(SIGTERM, remove_lock_file_on_signal);
- signal(SIGQUIT, remove_lock_file_on_signal);
- signal(SIGPIPE, remove_lock_file_on_signal);
+ sigchain_push(SIGINT, remove_lock_file_on_signal);
+ sigchain_push(SIGHUP, remove_lock_file_on_signal);
+ sigchain_push(SIGTERM, remove_lock_file_on_signal);
+ sigchain_push(SIGQUIT, remove_lock_file_on_signal);
+ sigchain_push(SIGPIPE, remove_lock_file_on_signal);
atexit(remove_lock_file);
}
lk->owner = getpid();
diff --git a/sigchain.c b/sigchain.c
new file mode 100644
index 0000000..a18d505
--- /dev/null
+++ b/sigchain.c
@@ -0,0 +1,43 @@
+#include "sigchain.h"
+#include "cache.h"
+
+#define SIGCHAIN_MAX_SIGNALS 32
+
+struct sigchain_signal {
+ sigchain_fun *old;
+ int n;
+ int alloc;
+};
+static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS];
+
+static void check_signum(int sig)
+{
+ if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS)
+ die("BUG: signal out of range: %d", sig);
+}
+
+int sigchain_push(int sig, sigchain_fun f)
+{
+ struct sigchain_signal *s = signals + sig;
+ check_signum(sig);
+
+ ALLOC_GROW(s->old, s->n + 1, s->alloc);
+ s->old[s->n] = signal(sig, f);
+ if (s->old[s->n] == SIG_ERR)
+ return -1;
+ s->n++;
+ return 0;
+}
+
+int sigchain_pop(int sig)
+{
+ struct sigchain_signal *s = signals + sig;
+ check_signum(sig);
+ if (s->n < 1)
+ return 0;
+
+ if (signal(sig, s->old[s->n - 1]) == SIG_ERR)
+ return -1;
+ s->n--;
+ return 0;
+}
diff --git a/sigchain.h b/sigchain.h
new file mode 100644
index 0000000..254ebb0
--- /dev/null
+++ b/sigchain.h
@@ -0,0 +1,9 @@
+#ifndef SIGCHAIN_H
+#define SIGCHAIN_H
+
+typedef void (*sigchain_fun)(int);
+
+int sigchain_push(int sig, sigchain_fun f);
+int sigchain_pop(int sig);
+
+#endif /* SIGCHAIN_H */
diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh
new file mode 100755
index 0000000..9707af7
--- /dev/null
+++ b/t/t0005-signals.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='signals work as we expect'
+. ./test-lib.sh
+
+cat >expect <<EOF
+three
+two
+one
+EOF
+
+test_expect_success 'sigchain works' '
+ test-sigchain >actual
+ case "$?" in
+ 130) true ;; # POSIX w/ SIGINT=2
+ 3) true ;; # Windows
+ *) false ;;
+ esac &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/test-sigchain.c b/test-sigchain.c
new file mode 100644
index 0000000..8747dea
--- /dev/null
+++ b/test-sigchain.c
@@ -0,0 +1,22 @@
+#include "sigchain.h"
+#include "cache.h"
+
+#define X(f) \
+static void f(int sig) { \
+ puts(#f); \
+ fflush(stdout); \
+ sigchain_pop(sig); \
+ raise(sig); \
+}
+X(one)
+X(two)
+X(three)
+#undef X
+
+int main(int argc, char **argv) {
+ sigchain_push(SIGINT, one);
+ sigchain_push(SIGINT, two);
+ sigchain_push(SIGINT, three);
+ raise(SIGINT);
+ return 0;
+}
--
1.6.1.403.g6c435
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 4/5] refactor signal handling for cleanup functions
2009-01-22 4:26 ` Jeff King
` (2 preceding siblings ...)
2009-01-22 6:02 ` [PATCH v2 3/5] chain kill signals for cleanup functions Jeff King
@ 2009-01-22 6:03 ` Jeff King
2009-01-22 6:03 ` [PATCH v2 5/5] pager: do wait_for_pager on signal death Jeff King
4 siblings, 0 replies; 23+ messages in thread
From: Jeff King @ 2009-01-22 6:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
The current code is very inconsistent about which signals
are caught for doing cleanup of temporary files and lock
files. Some callsites checked only SIGINT, while others
checked a variety of death-dealing signals.
This patch factors out those signals to a single function,
and then calls it everywhere. For some sites, that means
this is a simple clean up. For others, it is an improvement
in that they will now properly clean themselves up after a
larger variety of signals.
Signed-off-by: Jeff King <peff@peff.net>
---
Same as before, but needed rebasing due to previous diff.c changes.
builtin-clone.c | 2 +-
builtin-fetch--tool.c | 2 +-
builtin-fetch.c | 2 +-
diff.c | 2 +-
http-push.c | 5 +----
lockfile.c | 6 +-----
sigchain.c | 9 +++++++++
sigchain.h | 2 ++
8 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/builtin-clone.c b/builtin-clone.c
index 849cefc..313df6a 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -442,7 +442,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
}
junk_git_dir = git_dir;
atexit(remove_junk);
- sigchain_push(SIGINT, remove_junk_on_signal);
+ sigchain_push_common(remove_junk_on_signal);
setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1);
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index b1d7f8f..29356d2 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -246,7 +246,7 @@ static int fetch_native_store(FILE *fp,
char buffer[1024];
int err = 0;
- sigchain_push(SIGINT, remove_keep_on_signal);
+ sigchain_push_common(remove_keep_on_signal);
atexit(remove_keep);
while (fgets(buffer, sizeof(buffer), stdin)) {
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 8c86974..1e4a3d9 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -673,7 +673,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
ref_nr = j;
}
- sigchain_push(SIGINT, unlock_pack_on_signal);
+ sigchain_push_common(unlock_pack_on_signal);
atexit(unlock_pack);
exit_code = do_fetch(transport,
parse_fetch_refspec(ref_nr, refs), ref_nr);
diff --git a/diff.c b/diff.c
index dacd5d2..715709b 100644
--- a/diff.c
+++ b/diff.c
@@ -1905,7 +1905,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
if (!remove_tempfile_installed) {
atexit(remove_tempfile);
- sigchain_push(SIGINT, remove_tempfile_on_signal);
+ sigchain_push_common(remove_tempfile_on_signal);
remove_tempfile_installed = 1;
}
diff --git a/http-push.c b/http-push.c
index 4c92f80..178af75 100644
--- a/http-push.c
+++ b/http-push.c
@@ -2267,10 +2267,7 @@ int main(int argc, char **argv)
goto cleanup;
}
- sigchain_push(SIGINT, remove_locks_on_signal);
- sigchain_push(SIGHUP, remove_locks_on_signal);
- sigchain_push(SIGQUIT, remove_locks_on_signal);
- sigchain_push(SIGTERM, remove_locks_on_signal);
+ sigchain_push_common(remove_locks_on_signal);
/* Check whether the remote has server info files */
remote->can_update_info_refs = 0;
diff --git a/lockfile.c b/lockfile.c
index 3cd57dc..021c337 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -137,11 +137,7 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
if (0 <= lk->fd) {
if (!lock_file_list) {
- sigchain_push(SIGINT, remove_lock_file_on_signal);
- sigchain_push(SIGHUP, remove_lock_file_on_signal);
- sigchain_push(SIGTERM, remove_lock_file_on_signal);
- sigchain_push(SIGQUIT, remove_lock_file_on_signal);
- sigchain_push(SIGPIPE, remove_lock_file_on_signal);
+ sigchain_push_common(remove_lock_file_on_signal);
atexit(remove_lock_file);
}
lk->owner = getpid();
diff --git a/sigchain.c b/sigchain.c
index a18d505..1118b99 100644
--- a/sigchain.c
+++ b/sigchain.c
@@ -41,3 +41,12 @@ int sigchain_pop(int sig)
s->n--;
return 0;
}
+
+void sigchain_push_common(sigchain_fun f)
+{
+ sigchain_push(SIGINT, f);
+ sigchain_push(SIGHUP, f);
+ sigchain_push(SIGTERM, f);
+ sigchain_push(SIGQUIT, f);
+ sigchain_push(SIGPIPE, f);
+}
diff --git a/sigchain.h b/sigchain.h
index 254ebb0..618083b 100644
--- a/sigchain.h
+++ b/sigchain.h
@@ -6,4 +6,6 @@ typedef void (*sigchain_fun)(int);
int sigchain_push(int sig, sigchain_fun f);
int sigchain_pop(int sig);
+void sigchain_push_common(sigchain_fun f);
+
#endif /* SIGCHAIN_H */
--
1.6.1.403.g6c435
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 5/5] pager: do wait_for_pager on signal death
2009-01-22 4:26 ` Jeff King
` (3 preceding siblings ...)
2009-01-22 6:03 ` [PATCH v2 4/5] refactor signal handling " Jeff King
@ 2009-01-22 6:03 ` Jeff King
4 siblings, 0 replies; 23+ messages in thread
From: Jeff King @ 2009-01-22 6:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
Since ea27a18 (spawn pager via run_command interface), the
original git process actually does git work, and the pager
is a child process (actually, on Windows it has always been
that way, since Windows lacks fork). After spawning the
pager, we register an atexit() handler that waits for the
pager to finish.
Unfortunately, that handler does not always run. In
particular, if git is killed by a signal, then we exit
immediately. The calling shell then thinks that git is done;
however, the pager is still trying to run and impact the
terminal. The result can be seen by running a long git
process with a pager (e.g., "git log -p") and hitting ^C.
Depending on your config, you should see the shell prompt,
but pressing a key causes the pager to do any terminal
de-initialization sequence.
This patch just intercepts any death-dealing signals and
waits for the pager before dying. Under typical less
configuration, that means hitting ^C will cause git to stop
generating output, but the pager will keep running.
Signed-off-by: Jeff King <peff@peff.net>
---
Same as before.
| 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
--git a/pager.c b/pager.c
index f19ddbc..4921843 100644
--- a/pager.c
+++ b/pager.c
@@ -1,5 +1,6 @@
#include "cache.h"
#include "run-command.h"
+#include "sigchain.h"
/*
* This is split up from the rest of git so that we can do
@@ -38,6 +39,13 @@ static void wait_for_pager(void)
finish_command(&pager_process);
}
+static void wait_for_pager_signal(int signo)
+{
+ wait_for_pager();
+ sigchain_pop(signo);
+ raise(signo);
+}
+
void setup_pager(void)
{
const char *pager = getenv("GIT_PAGER");
@@ -75,6 +83,7 @@ void setup_pager(void)
close(pager_process.in);
/* this makes sure that the parent terminates after the pager */
+ sigchain_push_common(wait_for_pager_signal);
atexit(wait_for_pager);
}
--
1.6.1.403.g6c435
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)
2009-01-22 5:21 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Boyd Stephen Smith Jr.
@ 2009-01-23 6:23 ` Junio C Hamano
2009-01-27 1:43 ` Boyd Stephen Smith Jr.
1 sibling, 0 replies; 23+ messages in thread
From: Junio C Hamano @ 2009-01-23 6:23 UTC (permalink / raw)
To: Boyd Stephen Smith Jr.; +Cc: git
"Boyd Stephen Smith Jr." <bss@iguanasuicide.net> writes:
>>* js/diff-color-words (Tue Jan 20 21:46:57 2009 -0600) 8 commits
>> + color-words: Support diff.wordregex config option
>> + color-words: make regex configurable via attributes
>> + color-words: expand docs with precise semantics
>> + color-words: enable REG_NEWLINE to help user
>> + color-words: take an optional regular expression describing words
>> + color-words: change algorithm to allow for 0-character word
>> boundaries
>> + color-words: refactor word splitting and use ALLOC_GROW()
>> + Add color_fwrite_lines(), a function coloring each line
>> individually
>
> I think my patch in
> http://thread.gmane.org/gmane.comp.version-control.git/106567 should be
> applied to the top of this.
Thanks.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)
2009-01-22 5:21 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Boyd Stephen Smith Jr.
2009-01-23 6:23 ` Junio C Hamano
@ 2009-01-27 1:43 ` Boyd Stephen Smith Jr.
1 sibling, 0 replies; 23+ messages in thread
From: Boyd Stephen Smith Jr. @ 2009-01-27 1:43 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
[-- Attachment #1: Type: text/plain, Size: 951 bytes --]
On Wednesday 21 January 2009, "Boyd Stephen Smith Jr."
<bss@iguanasuicide.net> wrote about 'Re: What's cooking in git.git (Jan
2009, #05; Wed, 21)':
>On Wednesday 21 January 2009, Junio C Hamano <gitster@pobox.com> wrote
>about 'What's cooking in git.git (Jan 2009, #05; Wed, 21)':
>>* js/notes (Tue Jan 13 20:57:16 2009 +0100) 6 commits
>>
>>It would be nice to hear a real world success story using the notes
>>mechanism before casting this design in stone.
>
>I'll see if I can't try to put this through some paces over the week.
Yeah, that's not gonna happen. I still want to play with this some, but
that's being pushed to the background, so I can't say when I'll really get
time to test it.
--
Boyd Stephen Smith Jr. ,= ,-_-. =.
bss@iguanasuicide.net ((_/)o o(\_))
ICQ: 514984 YM/AIM: DaTwinkDaddy `-'(. .)`-'
http://iguanasuicide.net/ \_/
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/5] chain kill signals for cleanup functions
2009-01-22 6:02 ` [PATCH v2 3/5] chain kill signals for cleanup functions Jeff King
@ 2009-01-30 7:55 ` Jeff King
2009-01-30 8:13 ` Johannes Sixt
0 siblings, 1 reply; 23+ messages in thread
From: Jeff King @ 2009-01-30 7:55 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Junio C Hamano, git
On Thu, Jan 22, 2009 at 01:02:35AM -0500, Jeff King wrote:
> diff --git a/test-sigchain.c b/test-sigchain.c
> new file mode 100644
> index 0000000..8747dea
> --- /dev/null
> +++ b/test-sigchain.c
> [...]
> +int main(int argc, char **argv) {
> + sigchain_push(SIGINT, one);
> + sigchain_push(SIGINT, two);
> + sigchain_push(SIGINT, three);
> + raise(SIGINT);
> + return 0;
> +}
The signal-handling test was failing on my Solaris auto-build. After
much painful debugging, it seems that when running without a controlling
terminal (such as under cron), the signal handler for terminal related
signals (including SIGINT) is initialized to SIG_IGN. Thus after popping
all of our signal handlers, we restore the SIG_IGN, the program is _not_
killed by the signal, and the test fails.
One fix would be to just "signal(SIGINT, SIG_DFL)" at the top. But I
think it makes the test cleaner to just switch to a more reliable
signal. The patch would look something like what is below. But I need to
know what exit code Windows generates for SIGTERM. Johannes?
---
diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh
index 9707af7..09f855a 100755
--- a/t/t0005-signals.sh
+++ b/t/t0005-signals.sh
@@ -12,7 +12,7 @@ EOF
test_expect_success 'sigchain works' '
test-sigchain >actual
case "$?" in
- 130) true ;; # POSIX w/ SIGINT=2
+ 143) true ;; # POSIX w/ SIGTERM=15
3) true ;; # Windows
*) false ;;
esac &&
diff --git a/test-sigchain.c b/test-sigchain.c
index 8747dea..42db234 100644
--- a/test-sigchain.c
+++ b/test-sigchain.c
@@ -14,9 +14,9 @@ X(three)
#undef X
int main(int argc, char **argv) {
- sigchain_push(SIGINT, one);
- sigchain_push(SIGINT, two);
- sigchain_push(SIGINT, three);
- raise(SIGINT);
+ sigchain_push(SIGTERM, one);
+ sigchain_push(SIGTERM, two);
+ sigchain_push(SIGTERM, three);
+ raise(SIGTERM);
return 0;
}
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/5] chain kill signals for cleanup functions
2009-01-30 7:55 ` Jeff King
@ 2009-01-30 8:13 ` Johannes Sixt
2009-01-30 8:21 ` Jeff King
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Sixt @ 2009-01-30 8:13 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git
Jeff King schrieb:
> One fix would be to just "signal(SIGINT, SIG_DFL)" at the top. But I
> think it makes the test cleaner to just switch to a more reliable
> signal. The patch would look something like what is below. But I need to
> know what exit code Windows generates for SIGTERM. Johannes?
The same as with SIGINT: 3.
-- Hannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/5] chain kill signals for cleanup functions
2009-01-30 8:13 ` Johannes Sixt
@ 2009-01-30 8:21 ` Jeff King
2009-01-31 0:28 ` Junio C Hamano
0 siblings, 1 reply; 23+ messages in thread
From: Jeff King @ 2009-01-30 8:21 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Junio C Hamano, git
On Fri, Jan 30, 2009 at 09:13:00AM +0100, Johannes Sixt wrote:
> Jeff King schrieb:
> > One fix would be to just "signal(SIGINT, SIG_DFL)" at the top. But I
> > think it makes the test cleaner to just switch to a more reliable
> > signal. The patch would look something like what is below. But I need to
> > know what exit code Windows generates for SIGTERM. Johannes?
>
> The same as with SIGINT: 3.
Hmm. Clever.
Junio, can you apply this on top of the jk/signal-cleanup topic?
-- >8 --
Subject: [PATCH] t0005: use SIGTERM for sigchain test
The signal tests consists of checking that each of our
handlers is executed, and that the test program was killed
by the final signal. We arbitrarily used SIGINT as the kill
signal.
However, some platforms (notably Solaris) will default
SIGINT to SIG_IGN if there is no controlling terminal. In
that case, we don't end up killing the program with the
final signal and the test fails.
This is a problem since the test script should not depend
on outside factors; let's use SIGTERM instead, which should
behave consistently.
Signed-off-by: Jeff King <peff@peff.net>
---
t/t0005-signals.sh | 2 +-
test-sigchain.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh
index 9707af7..09f855a 100755
--- a/t/t0005-signals.sh
+++ b/t/t0005-signals.sh
@@ -12,7 +12,7 @@ EOF
test_expect_success 'sigchain works' '
test-sigchain >actual
case "$?" in
- 130) true ;; # POSIX w/ SIGINT=2
+ 143) true ;; # POSIX w/ SIGTERM=15
3) true ;; # Windows
*) false ;;
esac &&
diff --git a/test-sigchain.c b/test-sigchain.c
index 8747dea..42db234 100644
--- a/test-sigchain.c
+++ b/test-sigchain.c
@@ -14,9 +14,9 @@ X(three)
#undef X
int main(int argc, char **argv) {
- sigchain_push(SIGINT, one);
- sigchain_push(SIGINT, two);
- sigchain_push(SIGINT, three);
- raise(SIGINT);
+ sigchain_push(SIGTERM, one);
+ sigchain_push(SIGTERM, two);
+ sigchain_push(SIGTERM, three);
+ raise(SIGTERM);
return 0;
}
--
1.6.1.2.420.ga6a64.dirty
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/5] chain kill signals for cleanup functions
2009-01-30 8:21 ` Jeff King
@ 2009-01-31 0:28 ` Junio C Hamano
2009-01-31 1:44 ` Jeff King
0 siblings, 1 reply; 23+ messages in thread
From: Junio C Hamano @ 2009-01-31 0:28 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Sixt, git
Jeff King <peff@peff.net> writes:
> On Fri, Jan 30, 2009 at 09:13:00AM +0100, Johannes Sixt wrote:
>
>> Jeff King schrieb:
>> > One fix would be to just "signal(SIGINT, SIG_DFL)" at the top. But I
>> > think it makes the test cleaner to just switch to a more reliable
>> > signal. The patch would look something like what is below. But I need to
>> > know what exit code Windows generates for SIGTERM. Johannes?
>>
>> The same as with SIGINT: 3.
>
> Hmm. Clever.
>
> Junio, can you apply this on top of the jk/signal-cleanup topic?
Will do, but I've been sick today, haven't caught up with the list
traffic, and I do not think I'll be reading my mails for the rest of the
day either. It may take some time for it to appear in the public
repositories.
Thanks.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/5] chain kill signals for cleanup functions
2009-01-31 0:28 ` Junio C Hamano
@ 2009-01-31 1:44 ` Jeff King
2009-01-31 6:50 ` Jeff King
0 siblings, 1 reply; 23+ messages in thread
From: Jeff King @ 2009-01-31 1:44 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
On Fri, Jan 30, 2009 at 04:28:39PM -0800, Junio C Hamano wrote:
> > Hmm. Clever.
> >
> > Junio, can you apply this on top of the jk/signal-cleanup topic?
>
> Will do, but I've been sick today, haven't caught up with the list
> traffic, and I do not think I'll be reading my mails for the rest of the
> day either. It may take some time for it to appear in the public
> repositories.
No problem. It really is a fix for a false negative in the test, not any
actual git bug, so no rush.
Now I'm off to go make fun of you, buried deep in a thread where you
won't see it.
-Peff
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)
2009-01-22 5:13 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Johannes Schindelin
@ 2009-01-31 6:45 ` Sam Vilain
2009-01-31 7:36 ` Jeff King
0 siblings, 1 reply; 23+ messages in thread
From: Sam Vilain @ 2009-01-31 6:45 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, git
On Thu, 2009-01-22 at 06:13 +0100, Johannes Schindelin wrote:
> > It would be nice to hear a real world success story using the notes
> > mechanism before casting this design in stone.
>
> I'd like to have some profiling done before that. For example, I am still
> a bit unsure how the things would perform with a 50-deep delta chain for
> a notes tree having 50,000+ notes in it (which I think will not be all
> that unreasonable for a medium-sized project that stores bug-tracking
> information in the notes).
Is there any reason why the split has to be cast in stone at all?
ie, the code could just scan the root tree of the branch, and
progressively descend into sub-trees based on a partial match of the
object for which the note is to be found. If you find a partial name
then you expect that it is a tree and descend into it and scan for the
rest. If you find a complete name then you expect that it is a blob and
open it. If it turns out to be a tree then there are multiple notes for
that commit. Then I think you get the best of both worlds; you can
start with a simple flat structure and then later someone can come along
and make it split it when there are more than N entries in the root tree
(where N is determined from profiling etc).
There are two practical applications I could use this for straight away
for perl.git, and I think that they would be important use cases.
One would be to allow grafts to be noted. These might want to live in a
different place to refs/notes/commits, like refs/notes/grafts, to avoid
performance issues and to recognise they are a different type of data.
A second would be for commit header information - particularly the
author field and commit description - to be amended. I think this all
belongs under refs/notes/commits. These are in essence, historical
corrections that don't need to alter the tree.
The idea of making it allow a union merge seems relatively workable, I
think for simplicity and flexibility that the contents of the note
should be considered to be format-patch output (except without the diff
of course). So union-ish, more like a RFC822-aware merge of mail
messages.
eg, say the contents of the note are:
Some text
=> appends "Some text" to the note as currently implemented
Subject: Blah blah
Blah blah blah
=> _replaces_ commit message and body, as if it had been committed
with the above message
From: Sam Vilain <sam@vilain.net>
Date: Thu, 22 Jan 2009 06:13:01 +1300
Blah blah blah
=> replaces 'author' line in commit. "Blah blah blah" appended to
commit body.
Sound sane?
Sam.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/5] chain kill signals for cleanup functions
2009-01-31 1:44 ` Jeff King
@ 2009-01-31 6:50 ` Jeff King
2009-02-01 1:58 ` Junio C Hamano
0 siblings, 1 reply; 23+ messages in thread
From: Jeff King @ 2009-01-31 6:50 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Fri, Jan 30, 2009 at 08:44:20PM -0500, Jeff King wrote:
> > Will do, but I've been sick today, haven't caught up with the list
> > traffic, and I do not think I'll be reading my mails for the rest of the
> > day either. It may take some time for it to appear in the public
> > repositories.
> [...]
> Now I'm off to go make fun of you, buried deep in a thread where you
> won't see it.
Hmm, reading that again, it sounds mean, and I didn't mean it that way.
I should have put a ";P" at the end. What I meant was "while the cat is
away, the mice will play" (i.e., make mischief while our benevolent
dictator is out of commission).
Hope you feel better soon.
-Peff
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)
2009-01-31 6:45 ` Sam Vilain
@ 2009-01-31 7:36 ` Jeff King
2009-02-01 2:39 ` [PATCH] split notes [was: Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)] Sam Vilain
2009-02-01 3:09 ` Sam Vilain
0 siblings, 2 replies; 23+ messages in thread
From: Jeff King @ 2009-01-31 7:36 UTC (permalink / raw)
To: Sam Vilain; +Cc: Johannes Schindelin, Junio C Hamano, git
On Sat, Jan 31, 2009 at 07:45:54PM +1300, Sam Vilain wrote:
> Is there any reason why the split has to be cast in stone at all?
>
> ie, the code could just scan the root tree of the branch, and
> progressively descend into sub-trees based on a partial match of the
> object for which the note is to be found. If you find a partial name
> then you expect that it is a tree and descend into it and scan for the
> rest. If you find a complete name then you expect that it is a blob and
> open it. If it turns out to be a tree then there are multiple notes for
> that commit. Then I think you get the best of both worlds; you can
> start with a simple flat structure and then later someone can come along
> and make it split it when there are more than N entries in the root tree
> (where N is determined from profiling etc).
Actually, lookup is even easier than that: we iterate through the entire
tree recursively and add everything to a flat hash. So we really don't
care there what the layout is like (just take the first 40 characters of
any directory name as a hash).
But it violates the usual git principle of "content has a unique name".
What happens when I add "a/b" and you add "ab"? A dumb merge will let
both co-exist, but which one do you return for lookup?
> One would be to allow grafts to be noted. These might want to live in a
> different place to refs/notes/commits, like refs/notes/grafts, to avoid
> performance issues and to recognise they are a different type of data.
> A second would be for commit header information - particularly the
> author field and commit description - to be amended. I think this all
> belongs under refs/notes/commits. These are in essence, historical
> corrections that don't need to alter the tree.
I agree that there should be multiple note hierarchies, and multiple
keys within each hierarchy. I have posted some thoughts on that before
(and you should be able to find them searching for "notes" in the list
archive), but unfortunately I have not had time to sit down and really
work out a notes implementation that matches what I posted (which I
don't think is that far from Dscho's work in next).
And I think what you are proposing (here and in the rest of your
message) is that certain notes hierarchies may have particular formats
and semantics. And that sounds reasonable to me.
-Peff
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/5] chain kill signals for cleanup functions
2009-01-31 6:50 ` Jeff King
@ 2009-02-01 1:58 ` Junio C Hamano
0 siblings, 0 replies; 23+ messages in thread
From: Junio C Hamano @ 2009-02-01 1:58 UTC (permalink / raw)
To: Jeff King; +Cc: git
Jeff King <peff@peff.net> writes:
> On Fri, Jan 30, 2009 at 08:44:20PM -0500, Jeff King wrote:
>
>> > Will do, but I've been sick today, haven't caught up with the list
>> > traffic, and I do not think I'll be reading my mails for the rest of the
>> > day either. It may take some time for it to appear in the public
>> > repositories.
>> [...]
>> Now I'm off to go make fun of you, buried deep in a thread where you
>> won't see it.
>
> Hmm, reading that again, it sounds mean, and I didn't mean it that way.
> I should have put a ";P" at the end. What I meant was "while the cat is
> away, the mice will play" (i.e., make mischief while our benevolent
> dictator is out of commission).
>
> Hope you feel better soon.
Thanks. I guess not much happened on the list while I was sick in bed.
I'll try to take a bit more rest and catch up tomorrow.
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH] split notes [was: Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)]
2009-01-31 7:36 ` Jeff King
@ 2009-02-01 2:39 ` Sam Vilain
2009-02-01 3:09 ` Sam Vilain
1 sibling, 0 replies; 23+ messages in thread
From: Sam Vilain @ 2009-02-01 2:39 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Schindelin, Junio C Hamano, git
On Sat, 2009-01-31 at 02:36 -0500, Jeff King wrote:
> Actually, lookup is even easier than that: we iterate through the entire
> tree recursively and add everything to a flat hash. So we really don't
> care there what the layout is like (just take the first 40 characters of
> any directory name as a hash).
Sure, but if you do want to scale to a hundred thousand notes, then I
think it would pay to have a plan for making it lazy as required. ie,
if a run just wants notes for 20 commits and there are 256 sub-trees
then only read 20 of them. Doesn't matter if it's not implemented
initially of course, so long as the on-disk format is supported by the
tools in the first release they will be backward compatible. And it's
not that complicated; see attached.
> But it violates the usual git principle of "content has a unique name".
> What happens when I add "a/b" and you add "ab"? A dumb merge will let
> both co-exist, but which one do you return for lookup?
It should only be tools adding to it, the trees shouldn't be modified
directly by users. In the below patch I make these all get deleted on
'git notes edit'.
Depending on the semantics of the notes, it might not be an error to
have multiple notes for a commit. In my patch this is "tolerated" to
some extent but not supported by git-notes.sh porcelain yet.
> I agree that there should be multiple note hierarchies, and multiple
> keys within each hierarchy. I have posted some thoughts on that before
> (and you should be able to find them searching for "notes" in the list
> archive), but unfortunately I have not had time to sit down and really
> work out a notes implementation that matches what I posted (which I
> don't think is that far from Dscho's work in next).
I had a brief look and couldn't find it, this was about the best one I
found from you in terms of links to previous discussions;
http://kerneltrap.org/mailarchive/git/2008/12/16/4427794 If there's
another thread you'd like me to read please fish it out and respond!
The more messages we have linking to the previous discussions the
better :).
> And I think what you are proposing (here and in the rest of your
> message) is that certain notes hierarchies may have particular formats
> and semantics. And that sounds reasonable to me.
Yes that was one part of it. But also make a convention that the
'commits' notes, ie the default ones, an RFC822 message if they begin
with "known" headers. Then porcelain such as log can inject them into
the fields at the appropriate point.
Anyway, without further ado here's the XX/XXXX split patch.
Subject: [PATCH] git-notes: allow for arbitrary split of entries into sub-trees
It might later turn out for performance reasons that a single tree for
notes will not be sufficient. While this does not solve the
performance problem as it still loads the entire lot of notes into a
hash at start-up, it does mean that such a change does not have to
worry about backward compatibility with git versions that don't yet
support it.
Signed-off-by: Sam Vilain <sam@vilain.net>
---
git-notes.sh | 45 ++++++++++++++++++++++++++++++++++++++-------
notes.c | 39 ++++++++++++++++++++++++++++++++-------
t/t3301-notes.sh | 11 +++++++++++
3 files changed, 81 insertions(+), 14 deletions(-)
diff --git a/git-notes.sh b/git-notes.sh
index bfdbaa8..e07499f 100755
--- a/git-notes.sh
+++ b/git-notes.sh
@@ -10,15 +10,35 @@ ACTION="$1"; shift
test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="$(git config core.notesref)"
test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="refs/notes/commits"
+export GIT_NOTES_REF
COMMIT=$(git rev-parse --verify --default HEAD "$@") ||
die "Invalid commit: $@"
+NOTES_PATH=$COMMIT
+case "$GIT_NOTES_SPLIT" in
+ [1-9]|[1-4][0-9])
+ NOTES_PATH=$( echo $COMMIT | perl -pe 's{^(.{'$GIT_NOTES_SPLIT'})}{$1/}' )
+ ;;
+esac
MESSAGE="$GIT_DIR"/new-notes-$COMMIT
trap '
test -f "$MESSAGE" && rm "$MESSAGE"
' 0
+show_note() {
+ COMMIT=$1
+ NOTE_PATH=$( git ls-tree --name-only -r $GIT_NOTES_REF | perl -nle '
+ $x = $_; s{/}{}g;
+ if (m{'$COMMIT'}) {
+ print $x;
+ exit;
+ }
+ ' )
+ [ -n "$NOTE_PATH" ] &&
+ git cat-file blob $GIT_NOTES_REF:$NOTE_PATH
+}
+
case "$ACTION" in
edit)
GIT_NOTES_REF= git log -1 $COMMIT | sed "s/^/#/" > "$MESSAGE"
@@ -32,7 +52,7 @@ edit)
else
PARENT="-p $CURRENT_HEAD"
git read-tree "$GIT_NOTES_REF" || die "Could not read index"
- git cat-file blob :$COMMIT >> "$MESSAGE" 2> /dev/null
+ show_note $COMMIT >> "$MESSAGE"
fi
${VISUAL:-${EDITOR:-vi}} "$MESSAGE"
@@ -42,15 +62,26 @@ edit)
if [ -s "$MESSAGE" ]; then
BLOB=$(git hash-object -w "$MESSAGE") ||
die "Could not write into object database"
- git update-index --add --cacheinfo 0644 $BLOB $COMMIT ||
+ git update-index --add --cacheinfo 0644 $BLOB $NOTES_PATH ||
die "Could not write index"
else
- test -z "$CURRENT_HEAD" &&
- die "Will not initialise with empty tree"
- git update-index --force-remove $COMMIT ||
- die "Could not update index"
+ NOTES_PATH=dummy
fi
+ git ls-files | perl -nle '
+ $x = $_; s{/}{}g;
+ if (m{'$COMMIT'} and $x ne q{'$NOTES_PATH'}) {
+ print $x;
+ }' |
+ while read path
+ do
+ git update-index --force-remove $path ||
+ die "Could not update index"
+ done
+
+ [ -z "$(git ls-files)" -a -z "$CURRENT_HEAD" ] &&
+ die "Will not initialise with empty tree"
+
TREE=$(git write-tree) || die "Could not write tree"
NEW_HEAD=$(echo Annotate $COMMIT | git commit-tree $TREE $PARENT) ||
die "Could not annotate"
@@ -58,7 +89,7 @@ edit)
"$GIT_NOTES_REF" $NEW_HEAD $CURRENT_HEAD
;;
show)
- git show "$GIT_NOTES_REF":$COMMIT
+ show_note $COMMIT
;;
*)
usage
diff --git a/notes.c b/notes.c
index bd73784..d763b50 100644
--- a/notes.c
+++ b/notes.c
@@ -70,28 +70,53 @@ static void add_entry(const unsigned char *commit_sha1,
hashcpy(hash_map.entries[index].notes_sha1, notes_sha1);
}
-static void initialize_hash_map(const char *notes_ref_name)
+static void initialize_hash_map_recursive(const char *tree_sha1, const char *path)
{
unsigned char sha1[20], commit_sha1[20];
+ unsigned char path_combined[40];
unsigned mode;
struct tree_desc desc;
struct name_entry entry;
+ int length = strlen(path);
+ int length_combined;
void *buf;
- if (!notes_ref_name || read_ref(notes_ref_name, commit_sha1) ||
- get_tree_entry(commit_sha1, "", sha1, &mode))
+ strcpy(path_combined, path);
+
+ if (get_tree_entry(tree_sha1, "", sha1, &mode))
return;
buf = fill_tree_descriptor(&desc, sha1);
if (!buf)
- die("Could not read %s for notes-index", sha1_to_hex(sha1));
+ die("Could not read %s for notes-index", sha1_to_hex(tree_sha1));
+
+ while (tree_entry(&desc, &entry)) {
+ length_combined = length + strlen(entry.path);
+ if (length_combined >= 40) {
+ strncpy(path_combined + length, entry.path,
+ 41 - length);
+ if (!get_sha1(path_combined, commit_sha1))
+ add_entry(commit_sha1, entry.sha1);
+ }
+ else {
+ strcpy(path_combined + length, entry.path);
+ initialize_hash_map_recursive(entry.sha1, path_combined);
+ }
+ }
- while (tree_entry(&desc, &entry))
- if (!get_sha1(entry.path, commit_sha1))
- add_entry(commit_sha1, entry.sha1);
free(buf);
}
+static void initialize_hash_map(const char *notes_ref_name)
+{
+ unsigned char commit_sha1[20];
+
+ if (!notes_ref_name || read_ref(notes_ref_name, commit_sha1))
+ return;
+
+ initialize_hash_map_recursive( commit_sha1, "" );
+}
+
static unsigned char *lookup_notes(const unsigned char *commit_sha1)
{
int index;
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 9393a25..3734b55 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -92,4 +92,15 @@ test_expect_success 'show multi-line notes' '
test_cmp expect-multiline output
'
+test_expect_success 'create split notes tree' '
+ : > a4 &&
+ git add a4 &&
+ test_tick &&
+ git commit -m 4th &&
+ MSG="b4" GIT_NOTES_SPLIT=2 git notes edit &&
+ [ "$(git notes show)" = "b4" ] &&
+ [ -n "$(git ls-tree --name-only -r refs/notes/commits | grep /)" ] &&
+ [ -n "$(git log -1 | grep Notes:)" ]
+'
+
test_done
--
debian.1.5.6.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH] split notes [was: Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)]
2009-01-31 7:36 ` Jeff King
2009-02-01 2:39 ` [PATCH] split notes [was: Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)] Sam Vilain
@ 2009-02-01 3:09 ` Sam Vilain
2009-02-01 12:01 ` Jakub Narebski
1 sibling, 1 reply; 23+ messages in thread
From: Sam Vilain @ 2009-02-01 3:09 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Schindelin, Junio C Hamano, git
[re-sent with correct envelope from so hopefully it will get to the
list this time]
On Sat, 2009-01-31 at 02:36 -0500, Jeff King wrote:
> Actually, lookup is even easier than that: we iterate through the entire
> tree recursively and add everything to a flat hash. So we really don't
> care there what the layout is like (just take the first 40 characters of
> any directory name as a hash).
Sure, but if you do want to scale to a hundred thousand notes, then I
think it would pay to have a plan for making it lazy as required. ie,
if a run just wants notes for 20 commits and there are 256 sub-trees
then only read 20 of them. Doesn't matter if it's not implemented
initially of course, so long as the on-disk format is supported by the
tools in the first release they will be backward compatible. And it's
not that complicated; see attached.
> But it violates the usual git principle of "content has a unique name".
> What happens when I add "a/b" and you add "ab"? A dumb merge will let
> both co-exist, but which one do you return for lookup?
It should only be tools adding to it, the trees shouldn't be modified
directly by users. In the below patch I make these all get deleted on
'git notes edit'.
Depending on the semantics of the notes, it might not be an error to
have multiple notes for a commit. In my patch this is "tolerated" to
some extent but not supported by git-notes.sh porcelain yet.
> I agree that there should be multiple note hierarchies, and multiple
> keys within each hierarchy. I have posted some thoughts on that before
> (and you should be able to find them searching for "notes" in the list
> archive), but unfortunately I have not had time to sit down and really
> work out a notes implementation that matches what I posted (which I
> don't think is that far from Dscho's work in next).
I had a brief look and couldn't find it, this was about the best one I
found from you in terms of links to previous discussions;
http://kerneltrap.org/mailarchive/git/2008/12/16/4427794 If there's
another thread you'd like me to read please fish it out and respond!
The more messages we have linking to the previous discussions the
better :).
> And I think what you are proposing (here and in the rest of your
> message) is that certain notes hierarchies may have particular formats
> and semantics. And that sounds reasonable to me.
Yes that was one part of it. But also make a convention that the
'commits' notes, ie the default ones, an RFC822 message if they begin
with "known" headers. Then porcelain such as log can inject them into
the fields at the appropriate point.
Anyway, without further ado here's the XX/XXXX split patch.
Subject: [PATCH] git-notes: allow for arbitrary split of entries into sub-trees
It might later turn out for performance reasons that a single tree for
notes will not be sufficient. While this does not solve the
performance problem as it still loads the entire lot of notes into a
hash at start-up, it does mean that such a change does not have to
worry about backward compatibility with git versions that don't yet
support it.
Signed-off-by: Sam Vilain <sam@vilain.net>
---
git-notes.sh | 45 ++++++++++++++++++++++++++++++++++++++-------
notes.c | 39 ++++++++++++++++++++++++++++++++-------
t/t3301-notes.sh | 11 +++++++++++
3 files changed, 81 insertions(+), 14 deletions(-)
diff --git a/git-notes.sh b/git-notes.sh
index bfdbaa8..e07499f 100755
--- a/git-notes.sh
+++ b/git-notes.sh
@@ -10,15 +10,35 @@ ACTION="$1"; shift
test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="$(git config core.notesref)"
test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="refs/notes/commits"
+export GIT_NOTES_REF
COMMIT=$(git rev-parse --verify --default HEAD "$@") ||
die "Invalid commit: $@"
+NOTES_PATH=$COMMIT
+case "$GIT_NOTES_SPLIT" in
+ [1-9]|[1-4][0-9])
+ NOTES_PATH=$( echo $COMMIT | perl -pe 's{^(.{'$GIT_NOTES_SPLIT'})}{$1/}' )
+ ;;
+esac
MESSAGE="$GIT_DIR"/new-notes-$COMMIT
trap '
test -f "$MESSAGE" && rm "$MESSAGE"
' 0
+show_note() {
+ COMMIT=$1
+ NOTE_PATH=$( git ls-tree --name-only -r $GIT_NOTES_REF | perl -nle '
+ $x = $_; s{/}{}g;
+ if (m{'$COMMIT'}) {
+ print $x;
+ exit;
+ }
+ ' )
+ [ -n "$NOTE_PATH" ] &&
+ git cat-file blob $GIT_NOTES_REF:$NOTE_PATH
+}
+
case "$ACTION" in
edit)
GIT_NOTES_REF= git log -1 $COMMIT | sed "s/^/#/" > "$MESSAGE"
@@ -32,7 +52,7 @@ edit)
else
PARENT="-p $CURRENT_HEAD"
git read-tree "$GIT_NOTES_REF" || die "Could not read index"
- git cat-file blob :$COMMIT >> "$MESSAGE" 2> /dev/null
+ show_note $COMMIT >> "$MESSAGE"
fi
${VISUAL:-${EDITOR:-vi}} "$MESSAGE"
@@ -42,15 +62,26 @@ edit)
if [ -s "$MESSAGE" ]; then
BLOB=$(git hash-object -w "$MESSAGE") ||
die "Could not write into object database"
- git update-index --add --cacheinfo 0644 $BLOB $COMMIT ||
+ git update-index --add --cacheinfo 0644 $BLOB $NOTES_PATH ||
die "Could not write index"
else
- test -z "$CURRENT_HEAD" &&
- die "Will not initialise with empty tree"
- git update-index --force-remove $COMMIT ||
- die "Could not update index"
+ NOTES_PATH=dummy
fi
+ git ls-files | perl -nle '
+ $x = $_; s{/}{}g;
+ if (m{'$COMMIT'} and $x ne q{'$NOTES_PATH'}) {
+ print $x;
+ }' |
+ while read path
+ do
+ git update-index --force-remove $path ||
+ die "Could not update index"
+ done
+
+ [ -z "$(git ls-files)" -a -z "$CURRENT_HEAD" ] &&
+ die "Will not initialise with empty tree"
+
TREE=$(git write-tree) || die "Could not write tree"
NEW_HEAD=$(echo Annotate $COMMIT | git commit-tree $TREE $PARENT) ||
die "Could not annotate"
@@ -58,7 +89,7 @@ edit)
"$GIT_NOTES_REF" $NEW_HEAD $CURRENT_HEAD
;;
show)
- git show "$GIT_NOTES_REF":$COMMIT
+ show_note $COMMIT
;;
*)
usage
diff --git a/notes.c b/notes.c
index bd73784..d763b50 100644
--- a/notes.c
+++ b/notes.c
@@ -70,28 +70,53 @@ static void add_entry(const unsigned char *commit_sha1,
hashcpy(hash_map.entries[index].notes_sha1, notes_sha1);
}
-static void initialize_hash_map(const char *notes_ref_name)
+static void initialize_hash_map_recursive(const char *tree_sha1, const char *path)
{
unsigned char sha1[20], commit_sha1[20];
+ unsigned char path_combined[40];
unsigned mode;
struct tree_desc desc;
struct name_entry entry;
+ int length = strlen(path);
+ int length_combined;
void *buf;
- if (!notes_ref_name || read_ref(notes_ref_name, commit_sha1) ||
- get_tree_entry(commit_sha1, "", sha1, &mode))
+ strcpy(path_combined, path);
+
+ if (get_tree_entry(tree_sha1, "", sha1, &mode))
return;
buf = fill_tree_descriptor(&desc, sha1);
if (!buf)
- die("Could not read %s for notes-index", sha1_to_hex(sha1));
+ die("Could not read %s for notes-index", sha1_to_hex(tree_sha1));
+
+ while (tree_entry(&desc, &entry)) {
+ length_combined = length + strlen(entry.path);
+ if (length_combined >= 40) {
+ strncpy(path_combined + length, entry.path,
+ 41 - length);
+ if (!get_sha1(path_combined, commit_sha1))
+ add_entry(commit_sha1, entry.sha1);
+ }
+ else {
+ strcpy(path_combined + length, entry.path);
+ initialize_hash_map_recursive(entry.sha1, path_combined);
+ }
+ }
- while (tree_entry(&desc, &entry))
- if (!get_sha1(entry.path, commit_sha1))
- add_entry(commit_sha1, entry.sha1);
free(buf);
}
+static void initialize_hash_map(const char *notes_ref_name)
+{
+ unsigned char commit_sha1[20];
+
+ if (!notes_ref_name || read_ref(notes_ref_name, commit_sha1))
+ return;
+
+ initialize_hash_map_recursive( commit_sha1, "" );
+}
+
static unsigned char *lookup_notes(const unsigned char *commit_sha1)
{
int index;
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 9393a25..3734b55 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -92,4 +92,15 @@ test_expect_success 'show multi-line notes' '
test_cmp expect-multiline output
'
+test_expect_success 'create split notes tree' '
+ : > a4 &&
+ git add a4 &&
+ test_tick &&
+ git commit -m 4th &&
+ MSG="b4" GIT_NOTES_SPLIT=2 git notes edit &&
+ [ "$(git notes show)" = "b4" ] &&
+ [ -n "$(git ls-tree --name-only -r refs/notes/commits | grep /)" ] &&
+ [ -n "$(git log -1 | grep Notes:)" ]
+'
+
test_done
--
debian.1.5.6.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH] split notes [was: Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)]
2009-02-01 3:09 ` Sam Vilain
@ 2009-02-01 12:01 ` Jakub Narebski
0 siblings, 0 replies; 23+ messages in thread
From: Jakub Narebski @ 2009-02-01 12:01 UTC (permalink / raw)
To: git
Sam Vilain wrote:
> test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="$(git config core.notesref)"
> test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="refs/notes/commits"
GIT_NOTES_REF=$($(GIT_NOTES_REF:-$(git config core.notesref):-refs/notes/commits)
Or something like that.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2009-02-01 12:08 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-22 3:55 What's cooking in git.git (Jan 2009, #05; Wed, 21) Junio C Hamano
2009-01-22 4:26 ` Jeff King
2009-01-22 5:57 ` [PATCH v2 1/5] Windows: Fix signal numbers Jeff King
2009-01-22 5:59 ` [PATCH v2 2/5] diff: refactor tempfile cleanup handling Jeff King
2009-01-22 6:02 ` [PATCH v2 3/5] chain kill signals for cleanup functions Jeff King
2009-01-30 7:55 ` Jeff King
2009-01-30 8:13 ` Johannes Sixt
2009-01-30 8:21 ` Jeff King
2009-01-31 0:28 ` Junio C Hamano
2009-01-31 1:44 ` Jeff King
2009-01-31 6:50 ` Jeff King
2009-02-01 1:58 ` Junio C Hamano
2009-01-22 6:03 ` [PATCH v2 4/5] refactor signal handling " Jeff King
2009-01-22 6:03 ` [PATCH v2 5/5] pager: do wait_for_pager on signal death Jeff King
2009-01-22 5:13 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Johannes Schindelin
2009-01-31 6:45 ` Sam Vilain
2009-01-31 7:36 ` Jeff King
2009-02-01 2:39 ` [PATCH] split notes [was: Re: What's cooking in git.git (Jan 2009, #05; Wed, 21)] Sam Vilain
2009-02-01 3:09 ` Sam Vilain
2009-02-01 12:01 ` Jakub Narebski
2009-01-22 5:21 ` What's cooking in git.git (Jan 2009, #05; Wed, 21) Boyd Stephen Smith Jr.
2009-01-23 6:23 ` Junio C Hamano
2009-01-27 1:43 ` Boyd Stephen Smith Jr.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).