* Re: [PATCH 1/2] run-command: Add checks after execvp fails with EACCES
From: Frans Klaver @ 2011-12-14 14:31 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vliqguwhq.fsf@alter.siamese.dyndns.org>
On Tue, Dec 13, 2011 at 8:01 PM, Junio C Hamano <gitster@pobox.com> wrote:
>
> - That "have_..._ions()" is too long and ugly.
I half expected that one and I agree. I vaguely remember typing it,
deleting it and typing it again when I started on that one.
>
> - The only thing you care about this callsite is if you have enough
> permission to execute the "cmd".
>
> In fact, you should not unconditionally require read permissions here.
>
> $ chmod a-r $(type --path git) && /bin/ls -l $(type --path git)
> --wx--x--x 109 junio junio 5126580 Dec 13 09:47 /home/junio/git-active/bin/git
> $ /home/junio/git-active/bin/git --version
> git version 1.7.8.249.gb1b73
>
> You may need read permission when the file is a script (i.e. not binary
> executable).
[...]
> When checking if you can run "foo/bar/baz", directories "foo/" and "foo/bar/"
> do not have to be readable. They only have to have executable bit to allow
> descending into them, and typically this is called "searchable" (see man chmod).
>
> $ mkdir -p /var/tmp/a/b && cp $(type --path git) /var/tmp/a/b/git
> $ chmod 111 /var/tmp/a /var/tmp/a/b
> $ /var/tmp/a/b/git --version
> git version 1.7.8.249.gb1b73
>
> I'd suggest having two helper functions, instead of the single one with
> overlong "have...ions" name.
>
> - can_search_directory() checks with access(X_OK);
>
> - can_execute_file() checks with access(X_OK|R_OK), even though R_OK is
> not always needed.
On the whole I like the suggestion. We should probably take it a bit
further. Since the x and r bits basically have nothing to do with each
other, and we need +rx only on scripts, I could just rely on fopen()
for the +r check. I will still add the can_execute_file() and
can_search_dir() helpers to support readability, as access(path, X_OK)
means different things in the different contexts. I would then
probably go for is_searchable() and is_executable() as function names.
is_executable then means "is file and has executable flag set",
is_searchable means "is directory and has executable flag set".
Basically files won't be searchable and directories won't be
executable. If execvp fails on a command that is executable, but not
readable, it is definitely a script and we can generate an error in
that case. 1/2 would then probably use access(path, R_OK), while 2/2
would start using fopen.
Since fopen() uses the effective uid/gid, it then makes sense to use
eaccess(3) instead of access(2) if available. It would be stupid to
have bugs arise just because of a mismatch between the [ug]ids used by
the two access checks. I'm aware of the fact that eaccess isn't a
standard function, so a #define HAVE... fallback to at least access()
would probably be required.
>
> Use the former here where you check the directory that contains the
> command, and use the latter up above where you check the command that is
> supposed to be executable, and also down below after you checked sb.buf is
> a path to a file that may be the command that is supposed to be
> executable.
>
> Then patch 2/2 can extend can_execute() to enhance its support for scripts
> by reading the hash-bang line and validating it, etc.
I'd rather keep the hash-bang check outside of that function and use
can_execute/is_executable for checking the interpreter as well, if
only for keeping the possibility of easily promoting them into an API.
I'd rather move check_interpreter into where it's called now, but pull
out the logic to find the interpreter. This will keep the error text
generation in diagnose_execvp_eacces. I think the code will make more
sense this way. There's tons of more errors that can be caused by a
faulty interpreter, and it'll be easier to cover more cases this way
in the future.
Thanks for the insightful reviews so far.
Let me know what you think,
Frans
^ permalink raw reply
* Re: [PATCH 2/7] revert: allow cherry-pick --continue to commit before resuming
From: Ramkumar Ramachandra @ 2011-12-14 14:26 UTC (permalink / raw)
To: Jonathan Nieder
Cc: Johannes Sixt, Junio C Hamano, git, Christian Couder,
Martin von Zweigbergk, Jay Soffian
In-Reply-To: <20111210124925.GC22035@elie.hsd1.il.comcast.net>
Hi again,
Jonathan Nieder wrote:
> When "git cherry-pick ..bar" encounters conflicts, permit the operator
> to use cherry-pick --continue after resolving them as a shortcut for
> "git commit && git cherry-pick --continue" to record the resolution
> and carry on with the rest of the sequence.
Sounds good. I remember my implementation being quite complicated;
let's see how you've done this.
> Example: after encountering a conflict from running "git cherry-pick
> foo bar baz":
>
> CONFLICT (content): Merge conflict in main.c
> error: could not apply f78a8d98c... bar!
> hint: after resolving the conflicts, mark the corrected paths
> hint: with 'git add <paths>' or 'git rm <paths>'
> hint: and commit the result with 'git commit'
>
> We edit main.c to resolve the conflict, mark it acceptable with "git
> add main.c", and can run "cherry-pick --continue" to resume the
> sequence.
>
> $ git cherry-pick --continue
> [editor opens to confirm commit message]
> [master 78c8a8c98] bar!
> 1 files changed, 1 insertions(+), 1 deletions(-)
> [master 87ca8798c] baz!
> 1 files changed, 1 insertions(+), 1 deletions(-)
I like the presentation of this example: much clearer than my examples.
> builtin/revert.c | 23 ++++++-
> t/t3510-cherry-pick-sequence.sh | 139 ++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 156 insertions(+), 6 deletions(-)
Oh, good -- lots of new tests :)
> diff --git a/builtin/revert.c b/builtin/revert.c
> index 9f6c85c1..a43b4d85 100644
> --- a/builtin/revert.c
> +++ b/builtin/revert.c
> @@ -1038,18 +1038,35 @@ static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
> return 0;
> }
>
> +static int continue_single_pick(void)
> +{
> + const char *argv[] = { "commit", NULL };
> +
> + if (!file_exists(git_path("CHERRY_PICK_HEAD")) &&
> + !file_exists(git_path("REVERT_HEAD")))
> + return error(_("no cherry-pick or revert in progress"));
> + return run_command_v_opt(argv, RUN_GIT_CMD);
> +}
Very nice! I can see how the introduction of REVERT_HEAD simplifies things :)
I'm totally embarrassed by the horribly convoluted logic in the "New
sequencer workflow!" I posted earlier.
Note to self: don't capitalize error() messages.
> static int sequencer_continue(struct replay_opts *opts)
> {
> struct commit_list *todo_list = NULL;
>
> if (!file_exists(git_path(SEQ_TODO_FILE)))
> - return error(_("No %s in progress"), action_name(opts));
> + return continue_single_pick();
> read_populate_opts(&opts);
> read_populate_todo(&todo_list, opts);
>
> /* Verify that the conflict has been resolved */
> - if (!index_differs_from("HEAD", 0))
> - todo_list = todo_list->next;
> + if (file_exists(git_path("CHERRY_PICK_HEAD")) ||
> + file_exists(git_path("REVERT_HEAD"))) {
> + int ret = continue_single_pick();
> + if (ret)
> + return ret;
> + }
> + if (index_differs_from("HEAD", 0))
> + return error_dirty_index(opts);
> + todo_list = todo_list->next;
> return pick_commits(todo_list, opts);
> }
Very nicely done. I can see why 1/7 makes so much sense now: it
helps think of different operations independently.
> diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
> index 2c4c1c85..4d1883b7 100755
> --- a/t/t3510-cherry-pick-sequence.sh
> +++ b/t/t3510-cherry-pick-sequence.sh
> @@ -2,6 +2,7 @@
>
> test_description='Test cherry-pick continuation features
>
> + + conflicting: rewrites unrelated to conflicting
> + yetanotherpick: rewrites foo to e
> + anotherpick: rewrites foo to d
> + picked: rewrites foo to c
Note to self: this list of commits is becoming quite unwieldy. We
should probably refactor these sometime.
> @@ -27,6 +28,7 @@ test_cmp_rev () {
> }
>
> test_expect_success setup '
> + git config advice.detachedhead false
> echo unrelated >unrelated &&
> git add unrelated &&
> test_commit initial foo a &&
Huh, why are you moving this line up? Oh, right: there are
"test_commit" statements in the setup- good catch. This is unrelated
to your patch and should be a separate commit though.
> @@ -35,8 +37,8 @@ test_expect_success setup '
> test_commit picked foo c &&
> test_commit anotherpick foo d &&
> test_commit yetanotherpick foo e &&
> - git config advice.detachedhead false
> -
> + pristine_detach initial &&
> + test_commit conflicting unrelated
> '
Looks fishy- I wonder why you're doing this. Let's read ahead and find out.
> @@ -243,7 +245,66 @@ test_expect_success '--continue complains when there are unresolved conflicts' '
> test_must_fail git cherry-pick --continue
> '
>
> -test_expect_success '--continue continues after conflicts are resolved' '
> +test_expect_success '--continue of single cherry-pick' '
> + pristine_detach initial &&
> + echo c >expect &&
> + test_must_fail git cherry-pick picked &&
> + echo c >foo &&
> + git add foo &&
> + git cherry-pick --continue &&
> +
> + test_cmp expect foo &&
> + test_cmp_rev initial HEAD^ &&
> + git diff --exit-code HEAD &&
> + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
> +'
Beautiful. The tests I wrote are ugly in comparison :\
> +test_expect_success '--continue of single revert' '
> + pristine_detach initial &&
> + echo resolved >expect &&
> + echo "Revert \"picked\"" >expect.msg &&
> + test_must_fail git revert picked &&
> + echo resolved >foo &&
> + git add foo &&
> + git cherry-pick --continue &&
Huh? You're continuing a "git revert" with a a "git cherry-pick
--continue"? The current 'master' still uses a commit_list, and
doesn't allow mixed "pick" and "revert" instructions yet.
> + git diff --exit-code HEAD &&
> + test_cmp expect foo &&
> + test_cmp_rev initial HEAD^ &&
> + git diff-tree -s --pretty=tformat:%s HEAD >msg &&
> + test_cmp expect.msg msg &&
> + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
> + test_must_fail git rev-parse --verify REVERT_HEAD
> +'
A couple of notes:
1. I haven't used the "-s" flag of "git diff-tree" before, so I opened
up the documentation to find this:
By default, 'git diff-tree --stdin' shows differences,
either in machine-readable form (without '-p') or in patch
form (with '-p'). This output can be suppressed. It is
only useful with '-v' flag.
Very misleading. TODO: Fix this.
2. Why did you use "diff-tree" to get the commit message? Isn't
"cat-file commit" much more straightforward?
> +test_expect_success '--continue after resolving conflicts' '
> + pristine_detach initial &&
> + echo d >expect &&
> + cat >expect.log <<-\EOF &&
> + OBJID
> + :100644 100644 OBJID OBJID M foo
> + OBJID
> + :100644 100644 OBJID OBJID M foo
> + OBJID
> + :100644 100644 OBJID OBJID M unrelated
> + OBJID
> + :000000 100644 OBJID OBJID A foo
> + :000000 100644 OBJID OBJID A unrelated
> + EOF
> + test_must_fail git cherry-pick base..anotherpick &&
> + echo c >foo &&
> + git add foo &&
> + git cherry-pick --continue &&
> + {
> + git rev-list HEAD |
> + git diff-tree --root --stdin |
> + sed "s/$_x40/OBJID/g"
> + } >actual.log &&
> + test_cmp expect foo &&
> + test_cmp expect.log actual.log
> +'
Unchanged from the original: I suspect you've moved the generation of
expectation messages up to produce a clean diff.
> +test_expect_success '--continue after resolving conflicts and committing' '
> pristine_detach initial &&
> test_must_fail git cherry-pick base..anotherpick &&
> echo "c" >foo &&
Okay, the diff isn't all that clean :P
> +test_expect_success '--continue asks for help after resolving patch to nil' '
> + pristine_detach conflicting &&
> + test_must_fail git cherry-pick initial..picked &&
> +
> + test_cmp_rev unrelatedpick CHERRY_PICK_HEAD &&
> + git checkout HEAD -- unrelated &&
> + test_must_fail git cherry-pick --continue 2>msg &&
> + test_i18ngrep "The previous cherry-pick is now empty" msg
> +'
I thought it was a bad idea to grep for specific output messages,
because of their volatile nature? Remind me what this test has to do
with the rest of your patch?
> +test_expect_failure 'follow advice and skip nil patch' '
> + pristine_detach conflicting &&
> + test_must_fail git cherry-pick initial..picked &&
> +
> + git checkout HEAD -- unrelated &&
> + test_must_fail git cherry-pick --continue &&
> + git reset &&
> + git cherry-pick --continue &&
> +
> + git rev-list initial..HEAD >commits &&
> + test_line_count = 3 commits
> +'
Again, what does this test have to do with the rest of your patch?
> test_expect_success '--continue respects opts' '
> pristine_detach initial &&
> test_must_fail git cherry-pick -x base..anotherpick &&
> @@ -288,6 +372,29 @@ test_expect_success '--continue respects opts' '
> grep "cherry picked from" anotherpick_msg
> '
>
> +test_expect_success '--continue of single-pick respects -x' '
> + pristine_detach initial &&
> + test_must_fail git cherry-pick -x picked &&
> + echo c >foo &&
> + git add foo &&
> + git cherry-pick --continue &&
> + test_path_is_missing .git/sequencer &&
> + git cat-file commit HEAD >msg &&
> + grep "cherry picked from" msg
> +'
I'd have liked s/respects -x/respects opts/ here for symmetry with the
previous test.
> +test_expect_success '--continue respects -x in first commit in multi-pick' '
> + pristine_detach initial &&
> + test_must_fail git cherry-pick -x picked anotherpick &&
> + echo c >foo &&
> + git add foo &&
> + git cherry-pick --continue &&
> + test_path_is_missing .git/sequencer &&
> + git cat-file commit HEAD^ >msg &&
> + picked=$(git rev-parse --verify picked) &&
> + grep "cherry picked from.*$picked" msg
> +'
Can you explain why "first commit in a multi-pick" is a special case?
> @@ -306,6 +413,32 @@ test_expect_success '--signoff is not automatically propagated to resolved confl
> grep "Signed-off-by:" anotherpick_msg
> '
>
> +test_expect_success '--signoff dropped for implicit commit of resolution, multi-pick case' '
> + pristine_detach initial &&
> + test_must_fail git cherry-pick -s picked anotherpick &&
> + echo c >foo &&
> + git add foo &&
> + git cherry-pick --continue &&
> +
> + git diff --exit-code HEAD &&
> + test_cmp_rev initial HEAD^^ &&
> + git cat-file commit HEAD^ >msg &&
> + ! grep Signed-off-by: msg
> +'
Unrelated.
> +test_expect_success 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
> + pristine_detach initial &&
> + test_must_fail git cherry-pick -s picked &&
> + echo c >foo &&
> + git add foo &&
> + git cherry-pick --continue &&
> +
> + git diff --exit-code HEAD &&
> + test_cmp_rev initial HEAD^ &&
> + git cat-file commit HEAD >msg &&
> + ! grep Signed-off-by: msg
> +'
If the previous test were a separate patch preceding this one, this'd
belong here.
Thanks for working on this.
-- Ram
^ permalink raw reply
* [PATCH 3/3] Do not create commits whose message contains NUL
From: Nguyễn Thái Ngọc Duy @ 2011-12-14 14:08 UTC (permalink / raw)
To: git; +Cc: Jeff King, Miles Bader, Nguyễn Thái Ngọc Duy
In-Reply-To: <1323871699-8839-1-git-send-email-pclouds@gmail.com>
We assume that the commit log messages are uninterpreted sequences of
non-NUL bytes (see Documentation/i18n.txt). However the assumption
does not really stand out and it's quite easy to set an editor to save
in a NUL-included encoding. Currently we silently cut at the first NUL
we see.
Make it more obvious that NUL is not welcome by refusing to create
such commits. Those who deliberately want to create them can still do
with hash-object.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Documentation/config.txt | 4 ++++
advice.c | 2 ++
advice.h | 1 +
commit.c | 9 +++++++++
t/t3900-i18n-commit.sh | 6 ++++++
t/t3900/UTF-16.txt | Bin 0 -> 32 bytes
6 files changed, 22 insertions(+), 0 deletions(-)
create mode 100644 t/t3900/UTF-16.txt
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5a841da..daf57c2 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -144,6 +144,10 @@ advice.*::
Advice shown when you used linkgit::git-checkout[1] to
move to the detach HEAD state, to instruct how to create
a local branch after the fact. Default: true.
+ commitWideEncoding::
+ Advice shown when linkgit::git-commit[1] refuses to
+ proceed because there are NULs in commit message.
+ Default: true.
--
core.fileMode::
diff --git a/advice.c b/advice.c
index e02e632..130949e 100644
--- a/advice.c
+++ b/advice.c
@@ -6,6 +6,7 @@ int advice_commit_before_merge = 1;
int advice_resolve_conflict = 1;
int advice_implicit_identity = 1;
int advice_detached_head = 1;
+int advice_commmit_wide_encoding = 1;
static struct {
const char *name;
@@ -17,6 +18,7 @@ static struct {
{ "resolveconflict", &advice_resolve_conflict },
{ "implicitidentity", &advice_implicit_identity },
{ "detachedhead", &advice_detached_head },
+ { "commitwideencoding", &advice_commmit_wide_encoding },
};
void advise(const char *advice, ...)
diff --git a/advice.h b/advice.h
index e5d0af7..d913bdb 100644
--- a/advice.h
+++ b/advice.h
@@ -9,6 +9,7 @@ extern int advice_commit_before_merge;
extern int advice_resolve_conflict;
extern int advice_implicit_identity;
extern int advice_detached_head;
+extern int advice_commmit_wide_encoding;
int git_default_advice_config(const char *var, const char *value);
void advise(const char *advice, ...);
diff --git a/commit.c b/commit.c
index d67b8c7..59e5bce 100644
--- a/commit.c
+++ b/commit.c
@@ -855,6 +855,15 @@ int commit_tree(const char *msg, size_t msg_len, unsigned char *tree,
assert_sha1_type(tree, OBJ_TREE);
+ if (memchr(msg, '\0', msg_len)) {
+ error(_("your commit message contains NUL characters."));
+ if (advice_commmit_wide_encoding) {
+ advise(_("This is often caused by using wide encodings such as"));
+ advise(_("UTF-16. Please check your editor settings."));
+ }
+ return -1;
+ }
+
/* Not having i18n.commitencoding is the same as having utf-8 */
encoding_is_utf8 = is_encoding_utf8(git_commit_encoding);
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 1f62c15..d48a7c0 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -34,6 +34,12 @@ test_expect_success 'no encoding header for base case' '
test z = "z$E"
'
+test_expect_failure 'UTF-16 refused because of NULs' '
+ echo UTF-16 >F &&
+ git commit -a -F "$TEST_DIRECTORY"/t3900/UTF-16.txt
+'
+
+
for H in ISO8859-1 eucJP ISO-2022-JP
do
test_expect_success "$H setup" '
diff --git a/t/t3900/UTF-16.txt b/t/t3900/UTF-16.txt
new file mode 100644
index 0000000000000000000000000000000000000000..53296be684253f40964c0604be7fa7ff12e200cb
GIT binary patch
literal 32
mcmezOpWz6@X@-jo=NYasZ~@^#h9rjP3@HpR7}6Nh8Mpw;r3yp<
literal 0
HcmV?d00001
--
1.7.8.36.g69ee2
^ permalink raw reply related
* [PATCH 2/3] merge: abort if fails to commit
From: Nguyễn Thái Ngọc Duy @ 2011-12-14 14:08 UTC (permalink / raw)
To: git; +Cc: Jeff King, Miles Bader, Nguyễn Thái Ngọc Duy
In-Reply-To: <1323871699-8839-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/merge.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/builtin/merge.c b/builtin/merge.c
index df4548a..e57eefa 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -913,7 +913,9 @@ static int merge_trivial(struct commit *head)
parent->next->item = remoteheads->item;
parent->next->next = NULL;
prepare_to_commit();
- commit_tree(merge_msg.buf, merge_msg.len, result_tree, parent, result_commit, NULL);
+ if (commit_tree(merge_msg.buf, merge_msg.len,
+ result_tree, parent, result_commit, NULL))
+ die(_("failed to write commit object"));
finish(head, result_commit, "In-index merge");
drop_save();
return 0;
@@ -944,7 +946,9 @@ static int finish_automerge(struct commit *head,
strbuf_addch(&merge_msg, '\n');
prepare_to_commit();
free_commit_list(remoteheads);
- commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents, result_commit, NULL);
+ if (commit_tree(merge_msg.buf, merge_msg.len,
+ result_tree, parents, result_commit, NULL))
+ die(_("failed to write commit object"));
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
finish(head, result_commit, buf.buf);
strbuf_release(&buf);
--
1.7.8.36.g69ee2
^ permalink raw reply related
* [PATCH 1/3] Make commit_tree() take message length in addition to the commit message
From: Nguyễn Thái Ngọc Duy @ 2011-12-14 14:08 UTC (permalink / raw)
To: git; +Cc: Jeff King, Miles Bader, Nguyễn Thái Ngọc Duy
In-Reply-To: <1323871699-8839-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/commit-tree.c | 2 +-
builtin/commit.c | 2 +-
builtin/merge.c | 4 ++--
builtin/notes.c | 2 +-
commit.c | 4 ++--
commit.h | 2 +-
notes-cache.c | 2 +-
notes-merge.c | 8 ++++----
notes-merge.h | 2 +-
9 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index d083795..8fa384f 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -56,7 +56,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
if (strbuf_read(&buffer, 0, 0) < 0)
die_errno("git commit-tree: failed to read");
- if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
+ if (commit_tree(buffer.buf, buffer.len, tree_sha1, parents, commit_sha1, NULL)) {
strbuf_release(&buffer);
return 1;
}
diff --git a/builtin/commit.c b/builtin/commit.c
index 8f2bebe..ce0e47f 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1483,7 +1483,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
exit(1);
}
- if (commit_tree(sb.buf, active_cache_tree->sha1, parents, sha1,
+ if (commit_tree(sb.buf, sb.len, active_cache_tree->sha1, parents, sha1,
author_ident.buf)) {
rollback_index_files();
die(_("failed to write commit object"));
diff --git a/builtin/merge.c b/builtin/merge.c
index 2870a6a..df4548a 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -913,7 +913,7 @@ static int merge_trivial(struct commit *head)
parent->next->item = remoteheads->item;
parent->next->next = NULL;
prepare_to_commit();
- commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
+ commit_tree(merge_msg.buf, merge_msg.len, result_tree, parent, result_commit, NULL);
finish(head, result_commit, "In-index merge");
drop_save();
return 0;
@@ -944,7 +944,7 @@ static int finish_automerge(struct commit *head,
strbuf_addch(&merge_msg, '\n');
prepare_to_commit();
free_commit_list(remoteheads);
- commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
+ commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents, result_commit, NULL);
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
finish(head, result_commit, buf.buf);
strbuf_release(&buf);
diff --git a/builtin/notes.c b/builtin/notes.c
index f8e437d..d665459 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -306,7 +306,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
if (buf.buf[buf.len - 1] != '\n')
strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */
- create_notes_commit(t, NULL, buf.buf + 7, commit_sha1);
+ create_notes_commit(t, NULL, buf.buf + 7, buf.len - 7, commit_sha1);
update_ref(buf.buf, t->ref, commit_sha1, NULL, 0, DIE_ON_ERR);
strbuf_release(&buf);
diff --git a/commit.c b/commit.c
index 73b7e00..d67b8c7 100644
--- a/commit.c
+++ b/commit.c
@@ -845,7 +845,7 @@ static const char commit_utf8_warn[] =
"You may want to amend it after fixing the message, or set the config\n"
"variable i18n.commitencoding to the encoding your project uses.\n";
-int commit_tree(const char *msg, unsigned char *tree,
+int commit_tree(const char *msg, size_t msg_len, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
const char *author)
{
@@ -884,7 +884,7 @@ int commit_tree(const char *msg, unsigned char *tree,
strbuf_addch(&buffer, '\n');
/* And add the comment */
- strbuf_addstr(&buffer, msg);
+ strbuf_add(&buffer, msg, msg_len);
/* And check the encoding */
if (encoding_is_utf8 && !is_utf8(buffer.buf))
diff --git a/commit.h b/commit.h
index 009b113..1acaf53 100644
--- a/commit.h
+++ b/commit.h
@@ -181,7 +181,7 @@ static inline int single_parent(struct commit *commit)
struct commit_list *reduce_heads(struct commit_list *heads);
-extern int commit_tree(const char *msg, unsigned char *tree,
+extern int commit_tree(const char *msg, size_t msg_len, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
const char *author);
diff --git a/notes-cache.c b/notes-cache.c
index 4c8984e..04a5698 100644
--- a/notes-cache.c
+++ b/notes-cache.c
@@ -56,7 +56,7 @@ int notes_cache_write(struct notes_cache *c)
if (write_notes_tree(&c->tree, tree_sha1))
return -1;
- if (commit_tree(c->validity, tree_sha1, NULL, commit_sha1, NULL) < 0)
+ if (commit_tree(c->validity, strlen(c->validity), tree_sha1, NULL, commit_sha1, NULL) < 0)
return -1;
if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL,
0, QUIET_ON_ERR) < 0)
diff --git a/notes-merge.c b/notes-merge.c
index ce10aac..b3baaf4 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -530,7 +530,7 @@ static int merge_from_diffs(struct notes_merge_options *o,
}
void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
- const char *msg, unsigned char *result_sha1)
+ const char *msg, size_t msg_len, unsigned char *result_sha1)
{
unsigned char tree_sha1[20];
@@ -551,7 +551,7 @@ void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
/* else: t->ref points to nothing, assume root/orphan commit */
}
- if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL))
+ if (commit_tree(msg, msg_len, tree_sha1, parents, result_sha1, NULL))
die("Failed to commit notes tree to database");
}
@@ -669,7 +669,7 @@ int notes_merge(struct notes_merge_options *o,
commit_list_insert(remote, &parents); /* LIFO order */
commit_list_insert(local, &parents);
create_notes_commit(local_tree, parents, o->commit_msg.buf,
- result_sha1);
+ o->commit_msg.len, result_sha1);
}
found_result:
@@ -734,7 +734,7 @@ int notes_merge_commit(struct notes_merge_options *o,
}
create_notes_commit(partial_tree, partial_commit->parents, msg,
- result_sha1);
+ strlen(msg), result_sha1);
if (o->verbosity >= 4)
printf("Finalized notes merge commit: %s\n",
sha1_to_hex(result_sha1));
diff --git a/notes-merge.h b/notes-merge.h
index 168a672..fd52988 100644
--- a/notes-merge.h
+++ b/notes-merge.h
@@ -37,7 +37,7 @@ void init_notes_merge_options(struct notes_merge_options *o);
* The resulting commit SHA1 is stored in result_sha1.
*/
void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
- const char *msg, unsigned char *result_sha1);
+ const char *msg, size_t msg_len, unsigned char *result_sha1);
/*
* Merge notes from o->remote_ref into o->local_ref
--
1.7.8.36.g69ee2
^ permalink raw reply related
* [PATCH 0/3] git-commit rejects messages with NULs
From: Nguyễn Thái Ngọc Duy @ 2011-12-14 14:08 UTC (permalink / raw)
To: git; +Cc: Jeff King, Miles Bader, Nguyễn Thái Ngọc Duy
In-Reply-To: <1323777368-19697-1-git-send-email-pclouds@gmail.com>
Hi,
I'm sorry I forgot the patch that makes commit_tree() take message
length. This version rewords the error message and use memchr()
instead.
Nguyễn Thái Ngọc Duy (3):
Make commit_tree() take message length in addition to the commit
message
merge: abort if fails to commit
Do not create commits whose message contains NUL
Documentation/config.txt | 4 ++++
advice.c | 2 ++
advice.h | 1 +
builtin/commit-tree.c | 2 +-
builtin/commit.c | 2 +-
builtin/merge.c | 8 ++++++--
builtin/notes.c | 2 +-
commit.c | 13 +++++++++++--
commit.h | 2 +-
notes-cache.c | 2 +-
notes-merge.c | 8 ++++----
notes-merge.h | 2 +-
t/t3900-i18n-commit.sh | 6 ++++++
t/t3900/UTF-16.txt | Bin 0 -> 32 bytes
14 files changed, 40 insertions(+), 14 deletions(-)
create mode 100644 t/t3900/UTF-16.txt
--
1.7.8.36.g69ee2
^ permalink raw reply
* [PATCH v2 4/4] use wrapper for unchecked setenv/putenv calls
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
To: git; +Cc: peff, gitster, schwab
In-Reply-To: <1323871631-2872-1-git-send-email-kusmabite@gmail.com>
This avoids us from accidentally dropping state, possibly leading
to unexpected behaviour.
This is especially important on Windows, where the maximum size of
the environment is 32 kB.
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
builtin/clone.c | 2 +-
builtin/commit.c | 6 +++---
builtin/help.c | 4 ++--
builtin/init-db.c | 2 +-
builtin/merge.c | 4 ++--
builtin/notes.c | 2 +-
builtin/remote-ext.c | 4 ++--
builtin/revert.c | 2 +-
config.c | 2 +-
exec_cmd.c | 4 ++--
git.c | 18 +++++++++---------
| 2 +-
run-command.c | 2 +-
setup.c | 6 +++---
14 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/builtin/clone.c b/builtin/clone.c
index efe8b6c..8d81c29 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -566,7 +566,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
atexit(remove_junk);
sigchain_push_common(remove_junk_on_signal);
- setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
+ xsetenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
if (safe_create_leading_directories_const(git_dir) < 0)
die(_("could not create leading directories of '%s'"), git_dir);
diff --git a/builtin/commit.c b/builtin/commit.c
index e36e9ad..2b87da9 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -361,13 +361,13 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
die(_("unable to create temporary index"));
old_index_env = getenv(INDEX_ENVIRONMENT);
- setenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
+ xsetenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
die(_("interactive add failed"));
if (old_index_env && *old_index_env)
- setenv(INDEX_ENVIRONMENT, old_index_env, 1);
+ xsetenv(INDEX_ENVIRONMENT, old_index_env, 1);
else
unsetenv(INDEX_ENVIRONMENT);
@@ -1023,7 +1023,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
if (edit_flag)
use_editor = 1;
if (!use_editor)
- setenv("GIT_EDITOR", ":", 1);
+ xsetenv("GIT_EDITOR", ":", 1);
/* Sanity check options */
if (amend && !current_head)
diff --git a/builtin/help.c b/builtin/help.c
index 61ff798..e7dc15b 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -330,7 +330,7 @@ static void setup_man_path(void)
if (old_path)
strbuf_addstr(&new_path, old_path);
- setenv("MANPATH", new_path.buf, 1);
+ xsetenv("MANPATH", new_path.buf, 1);
strbuf_release(&new_path);
}
@@ -371,7 +371,7 @@ static void show_man_page(const char *git_cmd)
static void show_info_page(const char *git_cmd)
{
const char *page = cmd_to_page(git_cmd);
- setenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
+ xsetenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
execlp("info", "info", "gitman", page, (char *)NULL);
die("no info viewer handled the request");
}
diff --git a/builtin/init-db.c b/builtin/init-db.c
index d07554c..21ff09e 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -537,7 +537,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
if (is_bare_repository_cfg == 1) {
static char git_dir[PATH_MAX+1];
- setenv(GIT_DIR_ENVIRONMENT,
+ xsetenv(GIT_DIR_ENVIRONMENT,
getcwd(git_dir, sizeof(git_dir)), argc > 0);
}
diff --git a/builtin/merge.c b/builtin/merge.c
index a1c8534..a4ae473 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1257,7 +1257,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
strbuf_addstr(&buf, "merge");
for (i = 0; i < argc; i++)
strbuf_addf(&buf, " %s", argv[i]);
- setenv("GIT_REFLOG_ACTION", buf.buf, 0);
+ xsetenv("GIT_REFLOG_ACTION", buf.buf, 0);
strbuf_reset(&buf);
for (i = 0; i < argc; i++) {
@@ -1267,7 +1267,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
remotes = &commit_list_insert(commit, remotes)->next;
strbuf_addf(&buf, "GITHEAD_%s",
sha1_to_hex(commit->object.sha1));
- setenv(buf.buf, argv[i], 1);
+ xsetenv(buf.buf, argv[i], 1);
strbuf_reset(&buf);
if (merge_remote_util(commit) &&
merge_remote_util(commit)->obj &&
diff --git a/builtin/notes.c b/builtin/notes.c
index 10b8bc7..7b53c69 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -1076,7 +1076,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
struct strbuf sb = STRBUF_INIT;
strbuf_addstr(&sb, override_notes_ref);
expand_notes_ref(&sb);
- setenv("GIT_NOTES_REF", sb.buf, 1);
+ xsetenv("GIT_NOTES_REF", sb.buf, 1);
strbuf_release(&sb);
}
diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c
index 692c834..0b2169a 100644
--- a/builtin/remote-ext.c
+++ b/builtin/remote-ext.c
@@ -38,8 +38,8 @@ static char *strip_escapes(const char *str, const char *service,
psoff = 4;
/* Pass the service to command. */
- setenv("GIT_EXT_SERVICE", service, 1);
- setenv("GIT_EXT_SERVICE_NOPREFIX", service + psoff, 1);
+ xsetenv("GIT_EXT_SERVICE", service, 1);
+ xsetenv("GIT_EXT_SERVICE_NOPREFIX", service + psoff, 1);
/* Scan the length of argument. */
while (str[rpos] && (escape || str[rpos] != ' ')) {
diff --git a/builtin/revert.c b/builtin/revert.c
index 1ea525c..955a99f 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -1007,7 +1007,7 @@ static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
struct commit_list *cur;
int res;
- setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
+ xsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);
if (opts->allow_ff)
assert(!(opts->signoff || opts->no_commit ||
opts->record_origin || opts->edit));
diff --git a/config.c b/config.c
index 5ea101f..f461a62 100644
--- a/config.c
+++ b/config.c
@@ -43,7 +43,7 @@ void git_config_push_parameter(const char *text)
strbuf_addch(&env, ' ');
}
sq_quote_buf(&env, text);
- setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
+ xsetenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
strbuf_release(&env);
}
diff --git a/exec_cmd.c b/exec_cmd.c
index 171e841..a5a92dd 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -63,7 +63,7 @@ void git_set_argv_exec_path(const char *exec_path)
/*
* Propagate this setting to external programs.
*/
- setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
+ xsetenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
}
@@ -108,7 +108,7 @@ void setup_path(void)
else
strbuf_addstr(&new_path, _PATH_DEFPATH);
- setenv("PATH", new_path.buf, 1);
+ xsetenv("PATH", new_path.buf, 1);
strbuf_release(&new_path);
}
diff --git a/git.c b/git.c
index 8e34903..cb80de2 100644
--- a/git.c
+++ b/git.c
@@ -54,7 +54,7 @@ int check_pager_config(const char *cmd)
static void commit_pager_choice(void) {
switch (use_pager) {
case 0:
- setenv("GIT_PAGER", "cat", 1);
+ xsetenv("GIT_PAGER", "cat", 1);
break;
case 1:
setup_pager();
@@ -109,7 +109,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--no-replace-objects")) {
read_replace_refs = 0;
- setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
+ xsetenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--git-dir")) {
@@ -117,13 +117,13 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
fprintf(stderr, "No directory given for --git-dir.\n" );
usage(git_usage_string);
}
- setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
+ xsetenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
if (envchanged)
*envchanged = 1;
(*argv)++;
(*argc)--;
} else if (!prefixcmp(cmd, "--git-dir=")) {
- setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
+ xsetenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--namespace")) {
@@ -131,13 +131,13 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
fprintf(stderr, "No namespace given for --namespace.\n" );
usage(git_usage_string);
}
- setenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
+ xsetenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
if (envchanged)
*envchanged = 1;
(*argv)++;
(*argc)--;
} else if (!prefixcmp(cmd, "--namespace=")) {
- setenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
+ xsetenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--work-tree")) {
@@ -145,19 +145,19 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
fprintf(stderr, "No directory given for --work-tree.\n" );
usage(git_usage_string);
}
- setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
+ xsetenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
if (envchanged)
*envchanged = 1;
(*argv)++;
(*argc)--;
} else if (!prefixcmp(cmd, "--work-tree=")) {
- setenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
+ xsetenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--bare")) {
static char git_dir[PATH_MAX+1];
is_bare_repository_cfg = 1;
- setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
+ xsetenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "-c")) {
--git a/pager.c b/pager.c
index 975955b..d3a1299 100644
--- a/pager.c
+++ b/pager.c
@@ -76,7 +76,7 @@ void setup_pager(void)
if (!pager)
return;
- setenv("GIT_PAGER_IN_USE", "true", 1);
+ xsetenv("GIT_PAGER_IN_USE", "true", 1);
/* spawn the pager */
pager_argv[0] = pager;
diff --git a/run-command.c b/run-command.c
index 1c51043..37abbde 100644
--- a/run-command.c
+++ b/run-command.c
@@ -258,7 +258,7 @@ fail_pipe:
if (cmd->env) {
for (; *cmd->env; cmd->env++) {
if (strchr(*cmd->env, '='))
- putenv((char *)*cmd->env);
+ xputenv((char *)*cmd->env);
else
unsetenv(*cmd->env);
}
diff --git a/setup.c b/setup.c
index 61c22e6..06f38d0 100644
--- a/setup.c
+++ b/setup.c
@@ -309,7 +309,7 @@ void setup_work_tree(void)
* if $GIT_WORK_TREE is set relative
*/
if (getenv(GIT_WORK_TREE_ENVIRONMENT))
- setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
+ xsetenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
set_git_dir(relative_path(git_dir, work_tree));
initialized = 1;
@@ -683,9 +683,9 @@ const char *setup_git_directory_gently(int *nongit_ok)
prefix = setup_git_directory_gently_1(nongit_ok);
if (prefix)
- setenv("GIT_PREFIX", prefix, 1);
+ xsetenv("GIT_PREFIX", prefix, 1);
else
- setenv("GIT_PREFIX", "", 1);
+ xsetenv("GIT_PREFIX", "", 1);
if (startup_info) {
startup_info->have_repository = !nongit_ok || !*nongit_ok;
--
1.7.7.1.msysgit.0.272.g9e47e
^ permalink raw reply related
* [PATCH v2 3/4] wrapper: supply xsetenv and xputenv
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
To: git; +Cc: peff, gitster, schwab
In-Reply-To: <1323871631-2872-1-git-send-email-kusmabite@gmail.com>
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
git-compat-util.h | 2 ++
wrapper.c | 14 ++++++++++++++
2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/git-compat-util.h b/git-compat-util.h
index 77062ed..ab17d53 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -439,6 +439,8 @@ extern int xdup(int fd);
extern FILE *xfdopen(int fd, const char *mode);
extern int xmkstemp(char *template);
extern int xmkstemp_mode(char *template, int mode);
+extern int xsetenv(const char *name, const char *val, int override);
+extern int xputenv(const char *string);
extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
extern int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1);
diff --git a/wrapper.c b/wrapper.c
index 85f09df..8d172ac 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -381,3 +381,17 @@ int remove_or_warn(unsigned int mode, const char *file)
{
return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
}
+
+int xsetenv(const char *name, const char *val, int overwrite)
+{
+ if (setenv(name, val, overwrite))
+ die_errno("setenv failed to set '%s' to '%s'", name, val);
+ return 0;
+}
+
+int xputenv(const char *string)
+{
+ if (putenv(string))
+ die_errno("putenv failed to set '%s' ", string);
+ return 0;
+}
--
1.7.7.1.msysgit.0.272.g9e47e
^ permalink raw reply related
* [PATCH v2 2/4] compat/setenv.c: error if name contains '='
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
To: git; +Cc: peff, gitster, schwab
In-Reply-To: <1323871631-2872-1-git-send-email-kusmabite@gmail.com>
According to POSIX, setenv should error out with EINVAL if it's
asked to set an environment variable whose name contains an equals
sign. Implement this detail in our compatibility-fallback.
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
compat/setenv.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/compat/setenv.c b/compat/setenv.c
index 89947b7..fc1439a 100644
--- a/compat/setenv.c
+++ b/compat/setenv.c
@@ -6,7 +6,7 @@ int gitsetenv(const char *name, const char *value, int replace)
size_t namelen, valuelen;
char *envstr;
- if (!name || !value) {
+ if (!name || strchr(name, '=') || !value) {
errno = EINVAL;
return -1;
}
--
1.7.7.1.msysgit.0.272.g9e47e
^ permalink raw reply related
* [PATCH v2 1/4] compat/setenv.c: update errno when erroring out
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
To: git; +Cc: peff, gitster, schwab
In-Reply-To: <1323871631-2872-1-git-send-email-kusmabite@gmail.com>
Previously, gitsetenv didn't update errno as it should when
erroring out. Fix this.
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
compat/setenv.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/compat/setenv.c b/compat/setenv.c
index 3a22ea7..89947b7 100644
--- a/compat/setenv.c
+++ b/compat/setenv.c
@@ -6,7 +6,10 @@ int gitsetenv(const char *name, const char *value, int replace)
size_t namelen, valuelen;
char *envstr;
- if (!name || !value) return -1;
+ if (!name || !value) {
+ errno = EINVAL;
+ return -1;
+ }
if (!replace) {
char *oldval = NULL;
oldval = getenv(name);
@@ -16,7 +19,10 @@ int gitsetenv(const char *name, const char *value, int replace)
namelen = strlen(name);
valuelen = strlen(value);
envstr = malloc((namelen + valuelen + 2));
- if (!envstr) return -1;
+ if (!envstr) {
+ errno = ENOMEM;
+ return -1;
+ }
memcpy(envstr, name, namelen);
envstr[namelen] = '=';
--
1.7.7.1.msysgit.0.272.g9e47e
^ permalink raw reply related
* [PATCH v2 0/4] setenv/putenv errors
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
To: git; +Cc: peff, gitster, schwab
Here's v2 of this series. It grew a bit since the last round, as
I figured fixing the error-paths in compat/setenv.c made sense to
do while I was at it, considering how Windows (which is one of
the few likely platforms to be able to actually trigger this
issue) use it.
Erik Faye-Lund (4):
compat/setenv.c: update errno when erroring out
compat/setenv.c: error if name contains '='
wrapper: supply xsetenv and xputenv
use wrapper for unchecked setenv/putenv calls
builtin/clone.c | 2 +-
builtin/commit.c | 6 +++---
builtin/help.c | 4 ++--
builtin/init-db.c | 2 +-
builtin/merge.c | 4 ++--
builtin/notes.c | 2 +-
builtin/remote-ext.c | 4 ++--
builtin/revert.c | 2 +-
compat/setenv.c | 10 ++++++++--
config.c | 2 +-
exec_cmd.c | 4 ++--
git-compat-util.h | 2 ++
git.c | 18 +++++++++---------
pager.c | 2 +-
run-command.c | 2 +-
setup.c | 6 +++---
wrapper.c | 14 ++++++++++++++
17 files changed, 54 insertions(+), 32 deletions(-)
--
1.7.7.1.msysgit.0.272.g9e47e
^ permalink raw reply
* Re: [PATCH 1/7] revert: give --continue handling its own function
From: Ramkumar Ramachandra @ 2011-12-14 13:16 UTC (permalink / raw)
To: Jonathan Nieder
Cc: Johannes Sixt, Junio C Hamano, git, Christian Couder,
Martin von Zweigbergk, Jay Soffian
In-Reply-To: <20111210124736.GB22035@elie.hsd1.il.comcast.net>
Hi Jonathan,
Jonathan Nieder wrote:
> This makes pick_revisions() a little shorter and easier to read
> straight through.
Ah, yes: you've asked about this earlier. Sounds sane; let's read
ahead and see if anything jumps out.
> diff --git a/builtin/revert.c b/builtin/revert.c
> index 1ea525c1..9f6c85c1 100644
> --- a/builtin/revert.c
> +++ b/builtin/revert.c
> @@ -1038,6 +1038,21 @@ static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
> [...]
> +static int sequencer_continue(struct replay_opts *opts)
> +{
> + struct commit_list *todo_list = NULL;
> [...]
> static int pick_revisions(struct replay_opts *opts)
> {
> struct commit_list *todo_list = NULL;
> [...]
This is the only detailed that jumped out- you're filling up two
different commit_list structures, depending on whether we're
performing a fresh operation or continuing an existing one. Okay.
Thanks.
p.s- Sorry about the delay; just returned from a short vacation.
-- Ram
^ permalink raw reply
* Re: Branch names with slashes
From: Michael Haggerty @ 2011-12-14 12:52 UTC (permalink / raw)
To: Leonardo Kim; +Cc: git
In-Reply-To: <CAGcUY13TOodu1BO3DCoNnVvNZ9QkWAbD-RmyqQX6P1q6tcO+yg@mail.gmail.com>
On 12/14/2011 11:17 AM, Leonardo Kim wrote:
> Branch names can contain slashes, so we can use 'development/foo' as a
> branch name. If I choose 'development' as a branch name, it doesn't
> work. There is a directory named development at '.git/refs/heads'
> directory. So we cannot create a file named development for
> 'refs/heads/development'.
>
> An error message may occurs like below. Unfortunately, It is not of help to me.
> 'error: 'refs/heads/development/foo' exists; cannot create
> 'refs/heads/development'.
Assuming that the wording of the error message is not considered part of
the external API, it is trivial to change it. What do you suggest?
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply
* Re: [PATCH 1/2] set_ref_status_for_push(): use transport-flags abstraction
From: Thomas Adam @ 2011-12-14 10:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vsjkot5nc.fsf@alter.siamese.dyndns.org>
On 13 December 2011 23:26, Junio C Hamano <gitster@pobox.com> wrote:
> It does not make much sense to have separate "int" parameters to
> this function with two callsites (why do we need to to begin with?
This last bit should read:
"Why do we need two to begin with?"
Kindly,
-- Thomas Adam
^ permalink raw reply
* Re: [bug?] checkout -m doesn't work without a base version
From: Michael Schubert @ 2011-12-14 10:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Pete Harlan, git
In-Reply-To: <7vbormn8vk.fsf@alter.siamese.dyndns.org>
On 12/05/2011 07:58 PM, Junio C Hamano wrote:
> @@ -150,18 +155,27 @@ static int checkout_merged(int pos, struct checkout *state)
> int status;
> unsigned char sha1[20];
> mmbuffer_t result_buf;
> + unsigned char threeway[3][20];
> + unsigned mode;
> +
> + memset(threeway, 0, sizeof(threeway));
> + while (pos < active_nr) {
> + int stage;
> + stage = ce_stage(ce);
> + if (!stage || strcmp(path, ce->name))
> + break;
> + hashcpy(threeway[stage - 1], ce->sha1);
> + if (stage == 2)
> + mode = create_ce_mode(ce->ce_mode);
> + pos++;
> + ce = active_cache[pos];
> + }
> + if (is_null_sha1(threeway[1]) || is_null_sha1(threeway[2]))
> + return error(_("path '%s' does not have necessary versions"), path);
>
> - if (ce_stage(ce) != 1 ||
> - active_nr <= pos + 2 ||
> - strcmp(active_cache[pos+1]->name, path) ||
> - ce_stage(active_cache[pos+1]) != 2 ||
> - strcmp(active_cache[pos+2]->name, path) ||
> - ce_stage(active_cache[pos+2]) != 3)
> - return error(_("path '%s' does not have all 3 versions"), path);
> -
> - read_mmblob(&ancestor, active_cache[pos]->sha1);
> - read_mmblob(&ours, active_cache[pos+1]->sha1);
> - read_mmblob(&theirs, active_cache[pos+2]->sha1);
> + read_mmblob(&ancestor, threeway[0]);
> + read_mmblob(&ours, threeway[1]);
> + read_mmblob(&theirs, threeway[2]);
>
> /*
> * NEEDSWORK: re-create conflicts from merges with
> @@ -192,9 +206,7 @@ static int checkout_merged(int pos, struct checkout *state)
> if (write_sha1_file(result_buf.ptr, result_buf.size,
> blob_type, sha1))
> die(_("Unable to add merge result for '%s'"), path);
> - ce = make_cache_entry(create_ce_mode(active_cache[pos+1]->ce_mode),
> - sha1,
> - path, 2, 0);
> + ce = make_cache_entry(mode, sha1, path, 2, 0);
> if (!ce)
> die(_("make_cache_entry failed for path '%s'"), path);
> status = checkout_entry(ce, state, NULL);
gcc 4.6.2:
builtin/checkout.c: In function ‘cmd_checkout’:
builtin/checkout.c:210:5: warning: ‘mode’ may be used uninitialized in this function [-Wuninitialized]
builtin/checkout.c:160:11: note: ‘mode’ was declared here
^ permalink raw reply
* Branch names with slashes
From: Leonardo Kim @ 2011-12-14 10:17 UTC (permalink / raw)
To: git
Hi
Branch names can contain slashes, so we can use 'development/foo' as a
branch name. If I choose 'development' as a branch name, it doesn't
work. There is a directory named development at '.git/refs/heads'
directory. So we cannot create a file named development for
'refs/heads/development'.
An error message may occurs like below. Unfortunately, It is not of help to me.
'error: 'refs/heads/development/foo' exists; cannot create
'refs/heads/development'.
I think that dealing with a file system and an error message above is
not sufficient for a novice like me. I hope that it should be
improved.
Thanks for your response.
Leonardo YongUk KIM
^ permalink raw reply
* Re: [RFC/PATCH 0/7] some sequencer loose ends (Re: Fix revert --abort on Windows)
From: Jonathan Nieder @ 2011-12-14 9:57 UTC (permalink / raw)
To: Junio C Hamano
Cc: Johannes Sixt, Ramkumar Ramachandra, git, Christian Couder,
Martin von Zweigbergk, Jay Soffian
In-Reply-To: <7v39cp32av.fsf@alter.siamese.dyndns.org>
Junio C Hamano wrote:
> I saw a few minor nits in the log messages but otherwise nothing
> objectionable jumped at me from my initial reading of the series.
I was tempted to send a reroll with slightly better log messages once
I could see your corrections, but it looks like the series has been
merged to "next" and your corrections already leave me happy enough.
Thanks for looking it over.
^ permalink raw reply
* Re: [PATCH] test: errors preparing for a test are not special
From: Jonathan Nieder @ 2011-12-14 9:00 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Joe Ratterman, git, Junio C Hamano, Jeff King
In-Reply-To: <4EE863AF.2070606@viscovery.net>
Johannes Sixt wrote:
> At any rate, your patch makes the code much more comprehensible.
Thanks for the reminder and sanity-check.
^ permalink raw reply
* Re: [PATCH] Gitweb: Avoid warnings when a repo does not have a valid HEAD
From: Jonathan Nieder @ 2011-12-14 8:53 UTC (permalink / raw)
To: Joe Ratterman; +Cc: git, Jakub Narebski
In-Reply-To: <1323815706-10560-1-git-send-email-jratt0@gmail.com>
(just cc-ing Jakub)
Joe Ratterman wrote:
> It is possible that the HEAD reference does not point to an existing
> branch. When viewing such a repository in gitweb, a message like this
> one was sent to the error log:
>
> gitweb.cgi: Use of uninitialized value in string eq at /usr/src/git/gitweb/gitweb.cgi line 5115.
>
> Signed-off-by: Joe Ratterman <jratt0@gmail.com>
> ---
> gitweb/gitweb.perl | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
> index 4f0c3bd..5af06d6 100755
> --- a/gitweb/gitweb.perl
> +++ b/gitweb/gitweb.perl
> @@ -5440,7 +5440,7 @@ sub git_heads_body {
> for (my $i = $from; $i <= $to; $i++) {
> my $entry = $headlist->[$i];
> my %ref = %$entry;
> - my $curr = $ref{'id'} eq $head;
> + my $curr = $head ? ($ref{'id'} eq $head) : 0;
> if ($alternate) {
> print "<tr class=\"dark\">\n";
> } else {
> --
> 1.7.7.1
>
>
^ permalink raw reply
* Re: [PATCH] test: errors preparing for a test are not special
From: Johannes Sixt @ 2011-12-14 8:51 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: Joe Ratterman, git, Junio C Hamano, Jeff King
In-Reply-To: <20111214082203.GB13166@elie.hsd1.il.comcast.net>
Am 12/14/2011 9:22, schrieb Jonathan Nieder:
> Johannes Sixt wrote:
>> Am 12/13/2011 23:35, schrieb Joe Ratterman:
>
>>> test_expect_success TTY 'no pager with --no-pager' '
>>> rm -f paginated.out ||
>>> cleanup_fail &&
>>
>> What kind of bogosity do I see in the context of this hunk
> [...]
>> Wouldn't rm -f always succeed under normal circumstances, and then the
>> rest of the test would be skipped?
>
> No, && and || are left-associative.
<Facepalm/> You are right, of course, and I should have known better. (I
need more caffein.)
At any rate, your patch makes the code much more comprehensible.
-- Hannes
^ permalink raw reply
* Git difftool / mergetool on directory tree
From: Daniele Segato @ 2011-12-14 8:42 UTC (permalink / raw)
To: Git Mailing List
Hi,
many diff / merge tool around have the ability to compare a directory
tree (meld is one, but there are many).
Is there a way to start a difftool or a mergetool on a folder instead of
the single file?
It would be an handsome feature to git.
I googled a little before popping out this question and I only found
suggestion on how to open "many" file at once instead of opening them
serially but that's not the same thing not as powerful as directory
comparison.
Thanks,
Daniele
^ permalink raw reply
* [PATCH] test: errors preparing for a test are not special
From: Jonathan Nieder @ 2011-12-14 8:22 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Joe Ratterman, git, Junio C Hamano, Jeff King
In-Reply-To: <4EE853C0.20505@viscovery.net>
This script uses the following idiom to start each test in a known
good state:
test_expect_success 'some commands use a pager' '
rm -f paginated.out || cleanup_fail &&
test_terminal git log &&
test -e paginated.out
'
where "cleanup_fail" is a function that prints an error message and
errors out.
That is bogus on three levels:
- Cleanup commands like "rm -f" and "test_unconfig" are designed not
to fail, so this logic would never trip.
- If they were to malfunction anyway, it is not useful to set apart
cleanup commands as a special kind of failure with a special error
message. Whichever command fails, the next step is to investigate
which command that was, for example by running tests with
"prove -e 'sh -x'", and fix it.
- Relying on left-associativity of mixed &&/|| lists makes the code
somewhat cryptic.
The fix is simple: drop the "|| cleanup_fail" in each test and the
definition of the "cleanup_fail" function so no new callers can arise.
Reported-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Johannes Sixt wrote:
> Am 12/13/2011 23:35, schrieb Joe Ratterman:
>> test_expect_success TTY 'no pager with --no-pager' '
>> rm -f paginated.out ||
>> cleanup_fail &&
>
> What kind of bogosity do I see in the context of this hunk
[...]
> Wouldn't rm -f always succeed under normal circumstances, and then the
> rest of the test would be skipped?
No, && and || are left-associative.
That said, I think the || was a mistake. At the time, I had not yet
understood why some tests in other scripts had cleanup commands
outside the test body. I wrongly thought it was to make sure errors
during cleanup are not mistaken for errors in the test proper (rather
than to ensure cleanup happens when needed even if some tests are
skipped).
| 73 ++++++++++++-----------------------------------------
1 files changed, 17 insertions(+), 56 deletions(-)
--git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 320e1d1d..ff259084 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -6,11 +6,6 @@ test_description='Test automatic use of a pager.'
. "$TEST_DIRECTORY"/lib-pager.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
-cleanup_fail() {
- echo >&2 cleanup failed
- (exit 1)
-}
-
test_expect_success 'setup' '
sane_unset GIT_PAGER GIT_PAGER_IN_USE &&
test_unconfig core.pager &&
@@ -22,9 +17,7 @@ test_expect_success 'setup' '
'
test_expect_success TTY 'some commands use a pager' '
- rm -f paginated.out ||
- cleanup_fail &&
-
+ rm -f paginated.out &&
test_terminal git log &&
test -e paginated.out
'
@@ -45,49 +38,37 @@ test_expect_failure TTY 'pager runs from subdir' '
'
test_expect_success TTY 'some commands do not use a pager' '
- rm -f paginated.out ||
- cleanup_fail &&
-
+ rm -f paginated.out &&
test_terminal git rev-list HEAD &&
! test -e paginated.out
'
test_expect_success 'no pager when stdout is a pipe' '
- rm -f paginated.out ||
- cleanup_fail &&
-
+ rm -f paginated.out &&
git log | cat &&
! test -e paginated.out
'
test_expect_success 'no pager when stdout is a regular file' '
- rm -f paginated.out ||
- cleanup_fail &&
-
+ rm -f paginated.out &&
git log >file &&
! test -e paginated.out
'
test_expect_success TTY 'git --paginate rev-list uses a pager' '
- rm -f paginated.out ||
- cleanup_fail &&
-
+ rm -f paginated.out &&
test_terminal git --paginate rev-list HEAD &&
test -e paginated.out
'
test_expect_success 'no pager even with --paginate when stdout is a pipe' '
- rm -f file paginated.out ||
- cleanup_fail &&
-
+ rm -f file paginated.out &&
git --paginate log | cat &&
! test -e paginated.out
'
test_expect_success TTY 'no pager with --no-pager' '
- rm -f paginated.out ||
- cleanup_fail &&
-
+ rm -f paginated.out &&
test_terminal git --no-pager log &&
! test -e paginated.out
'
@@ -136,9 +117,7 @@ colorful() {
}
test_expect_success 'tests can detect color' '
- rm -f colorful.log colorless.log ||
- cleanup_fail &&
-
+ rm -f colorful.log colorless.log &&
git log --no-color >colorless.log &&
git log --color >colorful.log &&
! colorful colorless.log &&
@@ -147,18 +126,14 @@ test_expect_success 'tests can detect color' '
test_expect_success 'no color when stdout is a regular file' '
rm -f colorless.log &&
- test_config color.ui auto ||
- cleanup_fail &&
-
+ test_config color.ui auto &&
git log >colorless.log &&
! colorful colorless.log
'
test_expect_success TTY 'color when writing to a pager' '
rm -f paginated.out &&
- test_config color.ui auto ||
- cleanup_fail &&
-
+ test_config color.ui auto &&
(
TERM=vt100 &&
export TERM &&
@@ -181,9 +156,7 @@ test_expect_success TTY 'colors are suppressed by color.pager' '
test_expect_success 'color when writing to a file intended for a pager' '
rm -f colorful.log &&
- test_config color.ui auto ||
- cleanup_fail &&
-
+ test_config color.ui auto &&
(
TERM=vt100 &&
GIT_PAGER_IN_USE=true &&
@@ -242,9 +215,7 @@ test_default_pager() {
$test_expectation SIMPLEPAGER,TTY "$cmd - default pager is used by default" "
sane_unset PAGER GIT_PAGER &&
test_unconfig core.pager &&
- rm -f default_pager_used ||
- cleanup_fail &&
-
+ rm -f default_pager_used &&
cat >\$less <<-\EOF &&
#!/bin/sh
wc >default_pager_used
@@ -265,9 +236,7 @@ test_PAGER_overrides() {
$test_expectation TTY "$cmd - PAGER overrides default pager" "
sane_unset GIT_PAGER &&
test_unconfig core.pager &&
- rm -f PAGER_used ||
- cleanup_fail &&
-
+ rm -f PAGER_used &&
PAGER='wc >PAGER_used' &&
export PAGER &&
$full_command &&
@@ -292,9 +261,7 @@ test_core_pager() {
$test_expectation TTY "$cmd - repository-local core.pager setting $used_if_wanted" "
sane_unset GIT_PAGER &&
- rm -f core.pager_used ||
- cleanup_fail &&
-
+ rm -f core.pager_used &&
PAGER=wc &&
export PAGER &&
test_config core.pager 'wc >core.pager_used' &&
@@ -321,9 +288,7 @@ test_pager_subdir_helper() {
$test_expectation TTY "$cmd - core.pager $used_if_wanted from subdirectory" "
sane_unset GIT_PAGER &&
rm -f core.pager_used &&
- rm -fr sub ||
- cleanup_fail &&
-
+ rm -fr sub &&
PAGER=wc &&
stampname=\$(pwd)/core.pager_used &&
export PAGER stampname &&
@@ -341,9 +306,7 @@ test_GIT_PAGER_overrides() {
parse_args "$@"
$test_expectation TTY "$cmd - GIT_PAGER overrides core.pager" "
- rm -f GIT_PAGER_used ||
- cleanup_fail &&
-
+ rm -f GIT_PAGER_used &&
test_config core.pager wc &&
GIT_PAGER='wc >GIT_PAGER_used' &&
export GIT_PAGER &&
@@ -356,9 +319,7 @@ test_doesnt_paginate() {
parse_args "$@"
$test_expectation TTY "no pager for '$cmd'" "
- rm -f GIT_PAGER_used ||
- cleanup_fail &&
-
+ rm -f GIT_PAGER_used &&
GIT_PAGER='wc >GIT_PAGER_used' &&
export GIT_PAGER &&
$full_command &&
--
1.7.8
^ permalink raw reply related
* Re: [PATCH] Revert "http: don't always prompt for password"
From: Matthieu Moy @ 2011-12-14 8:20 UTC (permalink / raw)
To: Junio C Hamano
Cc: Jeff King, Stefan Naewe, Sebastian Schuberth, Eric, git, msysgit
In-Reply-To: <7vaa6wuqjt.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Jeff King <peff@peff.net> writes:
>
>> Doing (3) is obviously the easiest thing. And given the complexity of
>> the other two solutions, I think it makes sense to revert 986bbc08
>> (i.e., apply this patch), ship a working v1.7.8.1, and then look at
>> doing one of the other two solutions for v1.7.9.
>
> Or just let the "dumb HTTP" die.
>
> I thought push over DAV has long been dead; is anybody using it for real?
I am.
I'm working with people behind a firewall, hence HTTP is mandantory. My
lab has a webdav server, without Git installed on it. Being able to work
with this setup was one of the key feature of Git when I adopted it
(after a few years using GNU Arch the same way).
I could probably manage to convince my sysadmin to install Git on our
webserver, but I'd prefer if Git continues supporting my current setup.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: [PATCH] Add '-P' as a synonym for '--no-pager' in the git command
From: Johannes Sixt @ 2011-12-14 7:44 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: Joe Ratterman, git
In-Reply-To: <1323815706-10560-2-git-send-email-jratt0@gmail.com>
Am 12/13/2011 23:35, schrieb Joe Ratterman:
> +test_expect_success TTY 'no pager with -P' '
> + rm -f paginated.out ||
> + cleanup_fail &&
> +
> + test_terminal git -P log &&
> + ! test -e paginated.out
> +'
> +
> test_expect_success TTY 'no pager with --no-pager' '
> rm -f paginated.out ||
> cleanup_fail &&
What kind of bogosity do I see in the context of this hunk (and in the new
text as well, but it is not entirely your fault, Joe, since you obviously
have only copied an existing test snippet)?
Wouldn't rm -f always succeed under normal circumstances, and then the
rest of the test would be skipped? This use of || was introduced by
fdf1bc48 (t7006: guard cleanup with test_expect_success).
-- Hannes
^ permalink raw reply
* Re: [PATCH resend] Do not create commits whose message contains NUL
From: Jeff King @ 2011-12-14 7:17 UTC (permalink / raw)
To: Miles Bader; +Cc: Nguyễn Thái Ngọc Duy, git
In-Reply-To: <buomxavwwtq.fsf@dhlpc061.dev.necel.com>
On Wed, Dec 14, 2011 at 02:23:29PM +0900, Miles Bader wrote:
> Jeff King <peff@peff.net> writes:
> > But maybe it would be nicer to say something like:
> >
> > error: your commit message contains NUL characters.
> > hint: This is often caused by using multibyte encodings such as
> > hint: UTF-16. Please check your editor settings.
>
> I think the error message with the hint is much better for users, but
> isn't the term "multibyte" a little misleading here? It seems like
> it's really _wide_ encodings that are generally the culprit.
Yeah, wide is probably a better term. I'm not sure it is rigorously
defined anywhere, but in general I think it refers to the set of
encodings that do not care about the embedding of 8-bit ascii bytes as
subsets.
-Peff
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox