2013-06-12 02:13:00 +02:00
|
|
|
#include "cache.h"
|
2017-06-14 20:07:36 +02:00
|
|
|
#include "config.h"
|
2013-06-12 02:13:00 +02:00
|
|
|
#include "commit.h"
|
|
|
|
#include "refs.h"
|
|
|
|
#include "notes-utils.h"
|
2018-06-29 03:21:59 +02:00
|
|
|
#include "repository.h"
|
2013-06-12 02:13:01 +02:00
|
|
|
|
2019-01-12 03:13:23 +01:00
|
|
|
void create_notes_commit(struct repository *r,
|
|
|
|
struct notes_tree *t,
|
|
|
|
struct commit_list *parents,
|
2014-06-10 23:36:52 +02:00
|
|
|
const char *msg, size_t msg_len,
|
2018-01-28 01:13:16 +01:00
|
|
|
struct object_id *result_oid)
|
2013-06-12 02:13:01 +02:00
|
|
|
{
|
2017-05-07 00:10:04 +02:00
|
|
|
struct object_id tree_oid;
|
2013-06-12 02:13:01 +02:00
|
|
|
|
|
|
|
assert(t->initialized);
|
|
|
|
|
2018-01-28 01:13:18 +01:00
|
|
|
if (write_notes_tree(t, &tree_oid))
|
2013-06-12 02:13:01 +02:00
|
|
|
die("Failed to write notes tree to database");
|
|
|
|
|
|
|
|
if (!parents) {
|
|
|
|
/* Deduce parent commit from t->ref */
|
2017-05-07 00:10:04 +02:00
|
|
|
struct object_id parent_oid;
|
2017-10-16 00:06:56 +02:00
|
|
|
if (!read_ref(t->ref, &parent_oid)) {
|
2019-01-12 03:13:23 +01:00
|
|
|
struct commit *parent = lookup_commit(r, &parent_oid);
|
2013-10-24 10:53:19 +02:00
|
|
|
if (parse_commit(parent))
|
2013-06-12 02:13:01 +02:00
|
|
|
die("Failed to find/parse commit %s", t->ref);
|
|
|
|
commit_list_insert(parent, &parents);
|
|
|
|
}
|
|
|
|
/* else: t->ref points to nothing, assume root/orphan commit */
|
|
|
|
}
|
|
|
|
|
2018-01-28 01:13:16 +01:00
|
|
|
if (commit_tree(msg, msg_len, &tree_oid, parents, result_oid, NULL,
|
|
|
|
NULL))
|
2013-06-12 02:13:01 +02:00
|
|
|
die("Failed to commit notes tree to database");
|
|
|
|
}
|
2013-06-12 02:13:00 +02:00
|
|
|
|
2019-01-12 03:13:23 +01:00
|
|
|
void commit_notes(struct repository *r, struct notes_tree *t, const char *msg)
|
2013-06-12 02:13:00 +02:00
|
|
|
{
|
|
|
|
struct strbuf buf = STRBUF_INIT;
|
2017-05-07 00:10:04 +02:00
|
|
|
struct object_id commit_oid;
|
2013-06-12 02:13:00 +02:00
|
|
|
|
|
|
|
if (!t)
|
|
|
|
t = &default_notes_tree;
|
2015-10-08 04:54:43 +02:00
|
|
|
if (!t->initialized || !t->update_ref || !*t->update_ref)
|
2013-06-12 02:13:00 +02:00
|
|
|
die(_("Cannot commit uninitialized/unreferenced notes tree"));
|
|
|
|
if (!t->dirty)
|
|
|
|
return; /* don't have to commit an unchanged tree */
|
|
|
|
|
|
|
|
/* Prepare commit message and reflog message */
|
|
|
|
strbuf_addstr(&buf, msg);
|
2014-12-12 20:16:38 +01:00
|
|
|
strbuf_complete_line(&buf);
|
2013-06-12 02:13:00 +02:00
|
|
|
|
2019-01-12 03:13:23 +01:00
|
|
|
create_notes_commit(r, t, NULL, buf.buf, buf.len, &commit_oid);
|
2013-06-12 02:13:00 +02:00
|
|
|
strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */
|
2017-10-16 00:06:51 +02:00
|
|
|
update_ref(buf.buf, t->update_ref, &commit_oid, NULL, 0,
|
2014-04-07 15:47:56 +02:00
|
|
|
UPDATE_REFS_DIE_ON_ERR);
|
2013-06-12 02:13:00 +02:00
|
|
|
|
|
|
|
strbuf_release(&buf);
|
|
|
|
}
|
|
|
|
|
2015-08-17 23:33:31 +02:00
|
|
|
int parse_notes_merge_strategy(const char *v, enum notes_merge_strategy *s)
|
|
|
|
{
|
|
|
|
if (!strcmp(v, "manual"))
|
|
|
|
*s = NOTES_MERGE_RESOLVE_MANUAL;
|
|
|
|
else if (!strcmp(v, "ours"))
|
|
|
|
*s = NOTES_MERGE_RESOLVE_OURS;
|
|
|
|
else if (!strcmp(v, "theirs"))
|
|
|
|
*s = NOTES_MERGE_RESOLVE_THEIRS;
|
|
|
|
else if (!strcmp(v, "union"))
|
|
|
|
*s = NOTES_MERGE_RESOLVE_UNION;
|
|
|
|
else if (!strcmp(v, "cat_sort_uniq"))
|
|
|
|
*s = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-06-12 02:13:00 +02:00
|
|
|
static combine_notes_fn parse_combine_notes_fn(const char *v)
|
|
|
|
{
|
|
|
|
if (!strcasecmp(v, "overwrite"))
|
|
|
|
return combine_notes_overwrite;
|
|
|
|
else if (!strcasecmp(v, "ignore"))
|
|
|
|
return combine_notes_ignore;
|
|
|
|
else if (!strcasecmp(v, "concatenate"))
|
|
|
|
return combine_notes_concatenate;
|
|
|
|
else if (!strcasecmp(v, "cat_sort_uniq"))
|
|
|
|
return combine_notes_cat_sort_uniq;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int notes_rewrite_config(const char *k, const char *v, void *cb)
|
|
|
|
{
|
|
|
|
struct notes_rewrite_cfg *c = cb;
|
2013-11-30 21:55:40 +01:00
|
|
|
if (starts_with(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) {
|
2013-06-12 02:13:00 +02:00
|
|
|
c->enabled = git_config_bool(k, v);
|
|
|
|
return 0;
|
|
|
|
} else if (!c->mode_from_env && !strcmp(k, "notes.rewritemode")) {
|
|
|
|
if (!v)
|
2014-02-16 17:06:02 +01:00
|
|
|
return config_error_nonbool(k);
|
2013-06-12 02:13:00 +02:00
|
|
|
c->combine = parse_combine_notes_fn(v);
|
|
|
|
if (!c->combine) {
|
|
|
|
error(_("Bad notes.rewriteMode value: '%s'"), v);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
} else if (!c->refs_from_env && !strcmp(k, "notes.rewriteref")) {
|
|
|
|
/* note that a refs/ prefix is implied in the
|
|
|
|
* underlying for_each_glob_ref */
|
2013-11-30 21:55:40 +01:00
|
|
|
if (starts_with(v, "refs/notes/"))
|
2013-06-12 02:13:00 +02:00
|
|
|
string_list_add_refs_by_glob(c->refs, v);
|
|
|
|
else
|
|
|
|
warning(_("Refusing to rewrite notes in %s"
|
|
|
|
" (outside of refs/notes/)"), v);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd)
|
|
|
|
{
|
|
|
|
struct notes_rewrite_cfg *c = xmalloc(sizeof(struct notes_rewrite_cfg));
|
|
|
|
const char *rewrite_mode_env = getenv(GIT_NOTES_REWRITE_MODE_ENVIRONMENT);
|
|
|
|
const char *rewrite_refs_env = getenv(GIT_NOTES_REWRITE_REF_ENVIRONMENT);
|
|
|
|
c->cmd = cmd;
|
|
|
|
c->enabled = 1;
|
|
|
|
c->combine = combine_notes_concatenate;
|
|
|
|
c->refs = xcalloc(1, sizeof(struct string_list));
|
|
|
|
c->refs->strdup_strings = 1;
|
|
|
|
c->refs_from_env = 0;
|
|
|
|
c->mode_from_env = 0;
|
|
|
|
if (rewrite_mode_env) {
|
|
|
|
c->mode_from_env = 1;
|
|
|
|
c->combine = parse_combine_notes_fn(rewrite_mode_env);
|
|
|
|
if (!c->combine)
|
C style: use standard style for "TRANSLATORS" comments
Change all the "TRANSLATORS: [...]" comments in the C code to use the
regular Git coding style, and amend the style guide so that the
example there uses that style.
This custom style was necessary back in 2010 when the gettext support
was initially added, and was subsequently documented in commit
cbcfd4e3ea ("i18n: mention "TRANSLATORS:" marker in
Documentation/CodingGuidelines", 2014-04-18).
GNU xgettext hasn't had the parsing limitation that necessitated this
exception for almost 3 years. Since its 0.19 release on 2014-06-02
it's been able to recognize TRANSLATOR comments in the standard Git
comment syntax[1].
Usually we'd like to keep compatibility with software that's that
young, but in this case literally the only person who needs to be
using a gettext newer than 3 years old is Jiang Xin (the only person
who runs & commits "make pot" results), so I think in this case we can
make an exception.
This xgettext parsing feature was added after a thread on the Git
mailing list[2] which continued on the bug-gettext[3] list, but we
never subsequently changed our style & styleguide, do so.
There are already longstanding changes in git that use the standard
comment style & have their TRANSLATORS comments extracted properly
without getting the literal "*"'s mixed up in the text, as would
happen before xgettext 0.19.
Commit 7ff2683253 ("builtin-am: implement -i/--interactive",
2015-08-04) added one such comment, which in commit df0617bfa7 ("l10n:
git.pot: v2.6.0 round 1 (123 new, 41 removed)", 2015-09-05) got picked
up in the po/git.pot file with the right format, showing that Jiang
already runs a modern xgettext.
The xgettext parser does not handle the sort of non-standard comment
style that I'm amending here in sequencer.c, but that isn't standard
Git comment syntax anyway. With this change to sequencer.c & "make
pot" the comment in the pot file is now correct:
#. TRANSLATORS: %s will be "revert", "cherry-pick" or
-#. * "rebase -i".
+#. "rebase -i".
1. http://git.savannah.gnu.org/cgit/gettext.git/commit/?id=10af7fe6bd
2. <2ce9ec406501d112e032c8208417f8100bed04c6.1397712142.git.worldhello.net@gmail.com>
(https://public-inbox.org/git/2ce9ec406501d112e032c8208417f8100bed04c6.1397712142.git.worldhello.net@gmail.com/)
3. https://lists.gnu.org/archive/html/bug-gettext/2014-04/msg00016.html
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Acked-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-11 23:20:12 +02:00
|
|
|
/*
|
|
|
|
* TRANSLATORS: The first %s is the name of
|
|
|
|
* the environment variable, the second %s is
|
|
|
|
* its value.
|
|
|
|
*/
|
2013-06-12 02:13:00 +02:00
|
|
|
error(_("Bad %s value: '%s'"), GIT_NOTES_REWRITE_MODE_ENVIRONMENT,
|
|
|
|
rewrite_mode_env);
|
|
|
|
}
|
|
|
|
if (rewrite_refs_env) {
|
|
|
|
c->refs_from_env = 1;
|
|
|
|
string_list_add_refs_from_colon_sep(c->refs, rewrite_refs_env);
|
|
|
|
}
|
|
|
|
git_config(notes_rewrite_config, c);
|
|
|
|
if (!c->enabled || !c->refs->nr) {
|
|
|
|
string_list_clear(c->refs, 0);
|
|
|
|
free(c->refs);
|
|
|
|
free(c);
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-10-08 04:54:43 +02:00
|
|
|
c->trees = load_notes_trees(c->refs, NOTES_INIT_WRITABLE);
|
2013-06-12 02:13:00 +02:00
|
|
|
string_list_clear(c->refs, 0);
|
|
|
|
free(c->refs);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
|
2017-05-30 19:30:42 +02:00
|
|
|
const struct object_id *from_obj, const struct object_id *to_obj)
|
2013-06-12 02:13:00 +02:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
int i;
|
|
|
|
for (i = 0; c->trees[i]; i++)
|
|
|
|
ret = copy_note(c->trees[i], from_obj, to_obj, 1, c->combine) || ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-01-12 03:13:23 +01:00
|
|
|
void finish_copy_notes_for_rewrite(struct repository *r,
|
|
|
|
struct notes_rewrite_cfg *c,
|
|
|
|
const char *msg)
|
2013-06-12 02:13:00 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; c->trees[i]; i++) {
|
2019-01-12 03:13:23 +01:00
|
|
|
commit_notes(r, c->trees[i], msg);
|
2013-06-12 02:13:00 +02:00
|
|
|
free_notes(c->trees[i]);
|
|
|
|
}
|
|
|
|
free(c->trees);
|
|
|
|
free(c);
|
|
|
|
}
|