From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: Dave Olszewski <cxreg@pobox.com>, git@vger.kernel.org
Subject: Re: [PATCH 2/2] builtin/push.c: make push_default a static variable
Date: Wed, 18 Feb 2015 15:03:41 -0500 [thread overview]
Message-ID: <20150218200340.GA11861@peff.net> (raw)
In-Reply-To: <xmqq4mqj2e4j.fsf@gitster.dls.corp.google.com>
On Wed, Feb 18, 2015 at 11:50:20AM -0800, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>
> > On Wed, Feb 18, 2015 at 11:08:34AM -0800, Junio C Hamano wrote:
> > ...
> >> Not very strongly either way. Seeing the above does not bother me
> >> too much, but I do not know how I would feel when I start seeing
> >>
> >> val = git_config_book(k, v);
> >> flip_bool(val, &flags, TRANSPORT_PUSH_FOLLOW_TAGS);
> >>
> >> often. Not having to make sure that the bit constant whose name
> >> tends to get long is not misspelled is certainly a plus.
> >
> > I think it would be even nicer as:
> >
> > git_config_bits(k, v, &flags, TRANSPORT_PUSH_FOLLOW_TAGS);
>
> Maybe. I do not feel very strongly either way.
So I started to prepare a patch for this, because I wanted to see how it
would look. It's below in case you are curious, but note that it doesn't
compile, and that is does something a bit dangerous. So I think I am
giving up on this line of thought. Read on if you're curious.
The sticking point is the type of the bit-field. If it is:
void flip_bits(int set_or_clear, int *field, int bits);
then we cannot pass a pointer to "unsigned field". We can pass unsigned
bits, but note that we might lose the 32nd (or 64th) bit.
We can do this instead:
void flip_bits(int set_or_clear, void *field, unsigned bits);
But of course we will end up dereferencing "void *field" as "unsigned *".
I suspect if field is originally an "int" it works fine on most
platforms, but isn't legal according to the standard. Much worse,
though: if your original field is a different size, it's even less
likely to work. Passing a "char *" may set bits in random adjacent
memory (depending on your endianness), and an "unsigned long *" may set
bits in the wrong part of the variable. And because of the "void *", we
get no compiler warnings. :)
Add on top that we may want to use this for C bit-fields, whose address
cannot legally be taken (and this is why it does not compile).
So besides adding type-specific bit-flippers (yuck), I think the only
way to do it universally would be with a macro. Which I think tips it
over the "too gross, just write it out" line.
---
diff --git a/archive-tar.c b/archive-tar.c
index 0d1e6bd..3c794e2 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -352,10 +352,7 @@ static int tar_filter_config(const char *var, const char *value, void *data)
return 0;
}
if (!strcmp(type, "remote")) {
- if (git_config_bool(var, value))
- ar->flags |= ARCHIVER_REMOTE;
- else
- ar->flags &= ~ARCHIVER_REMOTE;
+ git_config_bits(var, value, &ar->flags, ARCHIVER_REMOTE);
return 0;
}
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index d816587..073445e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2216,10 +2216,8 @@ static int git_pack_config(const char *k, const char *v, void *cb)
return 0;
}
if (!strcmp(k, "pack.writebitmaphashcache")) {
- if (git_config_bool(k, v))
- write_bitmap_options |= BITMAP_OPT_HASH_CACHE;
- else
- write_bitmap_options &= ~BITMAP_OPT_HASH_CACHE;
+ git_config_bits(k, v, &write_bitmap_options,
+ BITMAP_OPT_HASH_CACHE);
}
if (!strcmp(k, "pack.usebitmaps")) {
use_bitmap_index = git_config_bool(k, v);
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 5878986..9d4eb24 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -53,10 +53,7 @@ static int mark_ce_flags(const char *path, int flag, int mark)
int namelen = strlen(path);
int pos = cache_name_pos(path, namelen);
if (0 <= pos) {
- if (mark)
- active_cache[pos]->ce_flags |= flag;
- else
- active_cache[pos]->ce_flags &= ~flag;
+ flip_bits(mark, &active_cache[pos]->ce_flags, flag);
active_cache[pos]->ce_flags |= CE_UPDATE_IN_BASE;
cache_tree_invalidate_path(&the_index, path);
active_cache_changed |= CE_ENTRY_CHANGED;
diff --git a/cache.h b/cache.h
index f704af5..957f150 100644
--- a/cache.h
+++ b/cache.h
@@ -1316,6 +1316,18 @@ extern int sha1_object_info_extended(const unsigned char *, struct object_info *
/* Dumb servers support */
extern int update_server_info(int);
+/*
+ * Either set or clear "bits" from "field", based on
+ * whether or not "set_or_clear" is set.
+ */
+static inline void flip_bits(int set_or_clear, void *field, unsigned bits)
+{
+ if (set_or_clear)
+ *(unsigned *)field |= bits;
+ else
+ *(unsigned *)field &= ~bits;
+}
+
/* git_config_parse_key() returns these negated: */
#define CONFIG_INVALID_KEY 1
#define CONFIG_NO_SECTION_OR_NAME 2
@@ -1385,6 +1397,12 @@ struct config_include_data {
#define CONFIG_INCLUDE_INIT { 0 }
extern int git_config_include(const char *name, const char *value, void *data);
+static inline int git_config_bits(const char *name, const char *value, void *field, unsigned bits)
+{
+ flip_bits(git_config_bool(name, value), field, bits);
+ return 0;
+}
+
/*
* Match and parse a config key of the form:
*
diff --git a/column.c b/column.c
index 786abe6..21c9765 100644
--- a/column.c
+++ b/column.c
@@ -281,12 +281,8 @@ static int parse_option(const char *arg, int len, unsigned int *colopts,
if (opts[i].mask)
*colopts = (*colopts & ~opts[i].mask) | opts[i].value;
- else {
- if (set)
- *colopts |= opts[i].value;
- else
- *colopts &= ~opts[i].value;
- }
+ else
+ flip_bits(set, colopts, opts[i].value);
return 0;
}
diff --git a/combine-diff.c b/combine-diff.c
index 91edce5..ad52b77 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -581,12 +581,9 @@ static int make_hunks(struct sline *sline, unsigned long cnt,
unsigned long i;
int has_interesting = 0;
- for (i = 0; i <= cnt; i++) {
- if (interesting(&sline[i], all_mask))
- sline[i].flag |= mark;
- else
- sline[i].flag &= ~mark;
- }
+ for (i = 0; i <= cnt; i++)
+ flip_bits(interesting(&sline[i], all_mask),
+ &sline[i].flag, mark);
if (!dense)
return give_context(sline, cnt, num_parent);
diff --git a/diff.c b/diff.c
index d1bd534..53b9481 100644
--- a/diff.c
+++ b/diff.c
@@ -3585,22 +3585,17 @@ static int parse_diff_filter_opt(const char *optarg, struct diff_options *opt)
for (i = 0; (optch = optarg[i]) != '\0'; i++) {
unsigned int bit;
- int negate;
+ int positive = 1;
if ('a' <= optch && optch <= 'z') {
- negate = 1;
+ positive = 0;
optch = toupper(optch);
- } else {
- negate = 0;
}
bit = (0 <= optch && optch <= 'Z') ? filter_bit[optch] : 0;
if (!bit)
return optarg[i];
- if (negate)
- opt->filter &= ~bit;
- else
- opt->filter |= bit;
+ flip_bits(positive, &opt->filter, bit);
}
return 0;
}
diff --git a/parse-options.c b/parse-options.c
index 80106c0..47c169c 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -100,17 +100,11 @@ static int get_value(struct parse_opt_ctx_t *p,
return (*(parse_opt_ll_cb *)opt->callback)(p, opt, unset);
case OPTION_BIT:
- if (unset)
- *(int *)opt->value &= ~opt->defval;
- else
- *(int *)opt->value |= opt->defval;
+ flip_bits(!unset, opt->value, opt->defval);
return 0;
case OPTION_NEGBIT:
- if (unset)
- *(int *)opt->value |= opt->defval;
- else
- *(int *)opt->value &= ~opt->defval;
+ flip_bits(unset, opt->value, opt->defval);
return 0;
case OPTION_COUNTUP:
diff --git a/revision.c b/revision.c
index 66520c6..85cb245 100644
--- a/revision.c
+++ b/revision.c
@@ -554,10 +554,8 @@ static int compact_treesame(struct rev_info *revs, struct commit *commit, unsign
if (nth_parent != 0)
die("compact_treesame %u", nth_parent);
old_same = !!(commit->object.flags & TREESAME);
- if (rev_same_tree_as_empty(revs, commit))
- commit->object.flags |= TREESAME;
- else
- commit->object.flags &= ~TREESAME;
+ flip_bits(rev_same_tree_as_empty(revs, commit),
+ &commit->object.flags, TREESAME);
return old_same;
}
@@ -578,10 +576,8 @@ static int compact_treesame(struct rev_info *revs, struct commit *commit, unsign
if (--st->nparents == 1) {
if (commit->parents->next)
die("compact_treesame parents mismatch");
- if (st->treesame[0] && revs->dense)
- commit->object.flags |= TREESAME;
- else
- commit->object.flags &= ~TREESAME;
+ flip_bits(st->treesame[0] && revs->dense,
+ &commit->object.flags, TREESAME);
free(add_decoration(&revs->treesame, &commit->object, NULL));
}
@@ -609,10 +605,8 @@ static unsigned update_treesame(struct rev_info *revs, struct commit *commit)
} else
irrelevant_change |= !st->treesame[n];
}
- if (relevant_parents ? relevant_change : irrelevant_change)
- commit->object.flags &= ~TREESAME;
- else
- commit->object.flags |= TREESAME;
+ flip_bits(!(relevant_parents ? relevant_change : irrelevant_change),
+ &commit->object.flags, TREESAME);
}
return commit->object.flags & TREESAME;
diff --git a/unpack-trees.c b/unpack-trees.c
index be84ba2..9089c5b 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -248,10 +248,8 @@ static int apply_sparse_checkout(struct index_state *istate,
{
int was_skip_worktree = ce_skip_worktree(ce);
- if (ce->ce_flags & CE_NEW_SKIP_WORKTREE)
- ce->ce_flags |= CE_SKIP_WORKTREE;
- else
- ce->ce_flags &= ~CE_SKIP_WORKTREE;
+ flip_bits(ce->ce_flags & CE_NEW_SKIP_WORKTREE,
+ &ce->ce_flags, CE_SKIP_WORKTREE);
if (was_skip_worktree != ce_skip_worktree(ce)) {
ce->ce_flags |= CE_UPDATE_IN_BASE;
istate->cache_changed |= CE_ENTRY_CHANGED;
@@ -982,10 +980,7 @@ static void mark_new_skip_worktree(struct exclude_list *el,
if (select_flag && !(ce->ce_flags & select_flag))
continue;
- if (!ce_stage(ce))
- ce->ce_flags |= skip_wt_flag;
- else
- ce->ce_flags &= ~skip_wt_flag;
+ flip_bits(!ce_stage(ce), &ce->ce_flags, skip_wt_flag);
}
/*
diff --git a/ws.c b/ws.c
index ea4b2b1..6c5f4bd 100644
--- a/ws.c
+++ b/ws.c
@@ -30,14 +30,14 @@ unsigned parse_whitespace_rule(const char *string)
int i;
size_t len;
const char *ep;
- int negated = 0;
+ int positive = 1;
string = string + strspn(string, ", \t\n\r");
ep = strchrnul(string, ',');
len = ep - string;
if (*string == '-') {
- negated = 1;
+ positive = 0;
string++;
len--;
}
@@ -47,10 +47,8 @@ unsigned parse_whitespace_rule(const char *string)
if (strncmp(whitespace_rule_names[i].rule_name,
string, len))
continue;
- if (negated)
- rule &= ~whitespace_rule_names[i].rule_bits;
- else
- rule |= whitespace_rule_names[i].rule_bits;
+ flip_bits(positive, &rule,
+ whitespace_rule_names[i].rule_bits);
break;
}
if (strncmp(string, "tabwidth=", 9) == 0) {
next prev parent reply other threads:[~2015-02-18 20:03 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-16 3:01 [PATCH] push: allow --follow-tags to be set by config push.followTags Dave Olszewski
2015-02-16 5:20 ` Jeff King
2015-02-16 5:45 ` [PATCH 0/2] clean up push config callbacks Jeff King
2015-02-16 5:46 ` [PATCH 1/2] git_push_config: drop cargo-culted wt_status pointer Jeff King
2015-02-16 5:47 ` [PATCH 2/2] builtin/push.c: make push_default a static variable Jeff King
2015-02-16 5:57 ` Junio C Hamano
2015-02-17 10:46 ` Jeff King
2015-02-17 17:45 ` Junio C Hamano
2015-02-17 18:23 ` Jeff King
2015-02-17 22:16 ` Junio C Hamano
2015-02-18 18:50 ` Jeff King
2015-02-18 19:08 ` Junio C Hamano
2015-02-18 19:25 ` Jeff King
2015-02-18 19:50 ` Junio C Hamano
2015-02-18 20:03 ` Jeff King [this message]
2015-02-16 5:54 ` [PATCH 3/2] push: allow --follow-tags to be set by config push.followTags Jeff King
2015-02-16 6:02 ` Junio C Hamano
2015-02-16 6:10 ` [PATCH 0/3] cleaner bit-setting in cmd_push Jeff King
2015-02-16 6:12 ` [PATCH 1/3] cmd_push: set "atomic" bit directly Jeff King
2015-02-16 6:13 ` [PATCH 2/3] cmd_push: pass "flags" pointer to config callback Jeff King
2015-02-16 7:05 ` Junio C Hamano
2015-02-16 7:16 ` Jeff King
2015-02-16 6:16 ` [PATCH 3/3] push: allow --follow-tags to be set by config push.followTags Jeff King
2015-03-14 6:06 ` Junio C Hamano
2015-03-14 17:34 ` Jeff King
2015-03-14 17:50 ` Dave Olszewski
2015-03-14 22:08 ` Junio C Hamano
2015-02-16 6:11 ` [PATCH 3/2] " Junio C Hamano
2015-02-16 6:17 ` Jeff King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150218200340.GA11861@peff.net \
--to=peff@peff.net \
--cc=cxreg@pobox.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).