#include "tag.h"
#include "submodule.h"
#include "worktree.h"
-#include "argv-array.h"
+#include "strvec.h"
#include "repository.h"
#include "sigchain.h"
return read_ref_full(refname, RESOLVE_REF_READING, oid, NULL);
}
-static int refs_ref_exists(struct ref_store *refs, const char *refname)
+int refs_ref_exists(struct ref_store *refs, const char *refname)
{
return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING, NULL, NULL);
}
* Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
* the results to 'prefixes'
*/
-void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
+void expand_ref_prefix(struct strvec *prefixes, const char *prefix)
{
const char **p;
int len = strlen(prefix);
for (p = ref_rev_parse_rules; *p; p++)
- argv_array_pushf(prefixes, *p, len, prefix);
+ strvec_pushf(prefixes, *p, len, prefix);
}
-char *repo_default_branch_name(struct repository *r)
+static const char default_branch_name_advice[] = N_(
+"Using '%s' as the name for the initial branch. This default branch name\n"
+"is subject to change. To configure the initial branch name to use in all\n"
+"of your new repositories, which will suppress this warning, call:\n"
+"\n"
+"\tgit config --global init.defaultBranch <name>\n"
+"\n"
+"Names commonly chosen instead of 'master' are 'main', 'trunk' and\n"
+"'development'. The just-created branch can be renamed via this command:\n"
+"\n"
+"\tgit branch -m <name>\n"
+);
+
+char *repo_default_branch_name(struct repository *r, int quiet)
{
const char *config_key = "init.defaultbranch";
const char *config_display_key = "init.defaultBranch";
char *ret = NULL, *full_ref;
+ const char *env = getenv("GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME");
- if (repo_config_get_string(r, config_key, &ret) < 0)
+ if (env && *env)
+ ret = xstrdup(env);
+ else if (repo_config_get_string(r, config_key, &ret) < 0)
die(_("could not retrieve `%s`"), config_display_key);
- if (!ret)
+ if (!ret) {
ret = xstrdup("master");
+ if (!quiet)
+ advise(_(default_branch_name_advice), ret);
+ }
full_ref = xstrfmt("refs/heads/%s", ret);
if (check_refname_format(full_ref, 0))
return ret;
}
-const char *git_default_branch_name(void)
+const char *git_default_branch_name(int quiet)
{
static char *ret;
if (!ret)
- ret = repo_default_branch_name(the_repository);
+ ret = repo_default_branch_name(the_repository, quiet);
return ret;
}
* to name a branch.
*/
static char *substitute_branch_name(struct repository *r,
- const char **string, int *len)
+ const char **string, int *len,
+ int nonfatal_dangling_mark)
{
struct strbuf buf = STRBUF_INIT;
- int ret = repo_interpret_branch_name(r, *string, *len, &buf, 0);
+ struct interpret_branch_name_options options = {
+ .nonfatal_dangling_mark = nonfatal_dangling_mark
+ };
+ int ret = repo_interpret_branch_name(r, *string, *len, &buf, &options);
if (ret == *len) {
size_t size;
}
int repo_dwim_ref(struct repository *r, const char *str, int len,
- struct object_id *oid, char **ref)
+ struct object_id *oid, char **ref, int nonfatal_dangling_mark)
{
- char *last_branch = substitute_branch_name(r, &str, &len);
+ char *last_branch = substitute_branch_name(r, &str, &len,
+ nonfatal_dangling_mark);
int refs_found = expand_ref(r, str, len, oid, ref);
free(last_branch);
return refs_found;
}
-int dwim_ref(const char *str, int len, struct object_id *oid, char **ref)
-{
- return repo_dwim_ref(the_repository, str, len, oid, ref);
-}
-
int expand_ref(struct repository *repo, const char *str, int len,
struct object_id *oid, char **ref)
{
struct object_id *oid, char **log)
{
struct ref_store *refs = get_main_ref_store(r);
- char *last_branch = substitute_branch_name(r, &str, &len);
+ char *last_branch = substitute_branch_name(r, &str, &len, 0);
const char **p;
int logs_found = 0;
struct strbuf path = STRBUF_INIT;
static int is_per_worktree_ref(const char *refname)
{
- return !strcmp(refname, "HEAD") ||
- starts_with(refname, "refs/worktree/") ||
- starts_with(refname, "refs/bisect/") ||
- starts_with(refname, "refs/rewritten/");
+ return starts_with(refname, "refs/worktree/") ||
+ starts_with(refname, "refs/bisect/") ||
+ starts_with(refname, "refs/rewritten/");
}
static int is_pseudoref_syntax(const char *refname)
return timeout_ms;
}
-static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
- const struct object_id *old_oid, struct strbuf *err)
-{
- const char *filename;
- int fd;
- struct lock_file lock = LOCK_INIT;
- struct strbuf buf = STRBUF_INIT;
- int ret = -1;
-
- if (!oid)
- return 0;
-
- strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
-
- filename = git_path("%s", pseudoref);
- fd = hold_lock_file_for_update_timeout(&lock, filename, 0,
- get_files_ref_lock_timeout_ms());
- if (fd < 0) {
- strbuf_addf(err, _("could not open '%s' for writing: %s"),
- filename, strerror(errno));
- goto done;
- }
-
- if (old_oid) {
- struct object_id actual_old_oid;
-
- if (read_ref(pseudoref, &actual_old_oid)) {
- if (!is_null_oid(old_oid)) {
- strbuf_addf(err, _("could not read ref '%s'"),
- pseudoref);
- rollback_lock_file(&lock);
- goto done;
- }
- } else if (is_null_oid(old_oid)) {
- strbuf_addf(err, _("ref '%s' already exists"),
- pseudoref);
- rollback_lock_file(&lock);
- goto done;
- } else if (!oideq(&actual_old_oid, old_oid)) {
- strbuf_addf(err, _("unexpected object ID when writing '%s'"),
- pseudoref);
- rollback_lock_file(&lock);
- goto done;
- }
- }
-
- if (write_in_full(fd, buf.buf, buf.len) < 0) {
- strbuf_addf(err, _("could not write to '%s'"), filename);
- rollback_lock_file(&lock);
- goto done;
- }
-
- commit_lock_file(&lock);
- ret = 0;
-done:
- strbuf_release(&buf);
- return ret;
-}
-
-static int delete_pseudoref(const char *pseudoref, const struct object_id *old_oid)
-{
- const char *filename;
-
- filename = git_path("%s", pseudoref);
-
- if (old_oid && !is_null_oid(old_oid)) {
- struct lock_file lock = LOCK_INIT;
- int fd;
- struct object_id actual_old_oid;
-
- fd = hold_lock_file_for_update_timeout(
- &lock, filename, 0,
- get_files_ref_lock_timeout_ms());
- if (fd < 0) {
- error_errno(_("could not open '%s' for writing"),
- filename);
- return -1;
- }
- if (read_ref(pseudoref, &actual_old_oid))
- die(_("could not read ref '%s'"), pseudoref);
- if (!oideq(&actual_old_oid, old_oid)) {
- error(_("unexpected object ID when deleting '%s'"),
- pseudoref);
- rollback_lock_file(&lock);
- return -1;
- }
-
- unlink(filename);
- rollback_lock_file(&lock);
- } else {
- unlink(filename);
- }
-
- return 0;
-}
-
int refs_delete_ref(struct ref_store *refs, const char *msg,
const char *refname,
const struct object_id *old_oid,
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
- if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
- assert(refs == get_main_ref_store(the_repository));
- return delete_pseudoref(refname, old_oid);
- }
-
transaction = ref_store_transaction_begin(refs, &err);
if (!transaction ||
ref_transaction_delete(transaction, refname, old_oid,
old_oid, flags);
}
-void copy_reflog_msg(struct strbuf *sb, const char *msg)
+static void copy_reflog_msg(struct strbuf *sb, const char *msg)
{
char c;
int wasspace = 1;
- strbuf_addch(sb, '\t');
while ((c = *msg++)) {
if (wasspace && isspace(c))
continue;
strbuf_rtrim(sb);
}
+static char *normalize_reflog_message(const char *msg)
+{
+ struct strbuf sb = STRBUF_INIT;
+
+ if (msg && *msg)
+ copy_reflog_msg(&sb, msg);
+ return strbuf_detach(&sb, NULL);
+}
+
int should_autocreate_reflog(const char *refname)
{
switch (log_all_ref_updates) {
oidcpy(&update->new_oid, new_oid);
if (flags & REF_HAVE_OLD)
oidcpy(&update->old_oid, old_oid);
- update->msg = xstrdup_or_null(msg);
+ update->msg = normalize_reflog_message(msg);
return update;
}
struct strbuf err = STRBUF_INIT;
int ret = 0;
- if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
- assert(refs == get_main_ref_store(the_repository));
- ret = write_pseudoref(refname, new_oid, old_oid, &err);
- } else {
- t = ref_store_transaction_begin(refs, &err);
- if (!t ||
- ref_transaction_update(t, refname, new_oid, old_oid,
- flags, msg, &err) ||
- ref_transaction_commit(t, &err)) {
- ret = 1;
- ref_transaction_free(t);
- }
+ t = ref_store_transaction_begin(refs, &err);
+ if (!t ||
+ ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
+ &err) ||
+ ref_transaction_commit(t, &err)) {
+ ret = 1;
+ ref_transaction_free(t);
}
if (ret) {
const char *str = _("update_ref failed for ref '%s': %s");
return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
}
+static int refs_read_special_head(struct ref_store *ref_store,
+ const char *refname, struct object_id *oid,
+ struct strbuf *referent, unsigned int *type)
+{
+ struct strbuf full_path = STRBUF_INIT;
+ struct strbuf content = STRBUF_INIT;
+ int result = -1;
+ strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
+
+ if (strbuf_read_file(&content, full_path.buf, 0) < 0)
+ goto done;
+
+ result = parse_loose_ref_contents(content.buf, oid, referent, type);
+
+done:
+ strbuf_release(&full_path);
+ strbuf_release(&content);
+ return result;
+}
+
int refs_read_raw_ref(struct ref_store *ref_store,
const char *refname, struct object_id *oid,
struct strbuf *referent, unsigned int *type)
{
- return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);
+ if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) {
+ return refs_read_special_head(ref_store, refname, oid, referent,
+ type);
+ }
+
+ return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
+ type);
}
/* This function needs to return a meaningful errno on failure */
BUG("attempting to get main_ref_store outside of repository");
r->refs_private = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS);
+ r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private);
return r->refs_private;
}
const char *refs_heads_master,
const char *logmsg)
{
- return refs->be->create_symref(refs, ref_target,
- refs_heads_master,
- logmsg);
+ char *msg;
+ int retval;
+
+ msg = normalize_reflog_message(logmsg);
+ retval = refs->be->create_symref(refs, ref_target, refs_heads_master,
+ msg);
+ free(msg);
+ return retval;
}
int create_symref(const char *ref_target, const char *refs_heads_master,
return 0;
}
-static const char hook_not_found;
-static const char *hook;
-
static int run_transaction_hook(struct ref_transaction *transaction,
const char *state)
{
struct child_process proc = CHILD_PROCESS_INIT;
struct strbuf buf = STRBUF_INIT;
+ const char *hook;
int ret = 0, i;
- if (hook == &hook_not_found)
- return ret;
+ hook = find_hook("reference-transaction");
if (!hook)
- hook = find_hook("reference-transaction");
- if (!hook) {
- hook = &hook_not_found;
return ret;
- }
- argv_array_pushl(&proc.args, hook, state, NULL);
+ strvec_pushl(&proc.args, hook, state, NULL);
proc.in = -1;
proc.stdout_to_stderr = 1;
proc.trace2_hook_name = "reference-transaction";
return refs->be->initial_transaction_commit(refs, transaction, err);
}
-int refs_delete_refs(struct ref_store *refs, const char *msg,
+int refs_delete_refs(struct ref_store *refs, const char *logmsg,
struct string_list *refnames, unsigned int flags)
{
- return refs->be->delete_refs(refs, msg, refnames, flags);
+ char *msg;
+ int retval;
+
+ msg = normalize_reflog_message(logmsg);
+ retval = refs->be->delete_refs(refs, msg, refnames, flags);
+ free(msg);
+ return retval;
}
int delete_refs(const char *msg, struct string_list *refnames,
int refs_rename_ref(struct ref_store *refs, const char *oldref,
const char *newref, const char *logmsg)
{
- return refs->be->rename_ref(refs, oldref, newref, logmsg);
+ char *msg;
+ int retval;
+
+ msg = normalize_reflog_message(logmsg);
+ retval = refs->be->rename_ref(refs, oldref, newref, msg);
+ free(msg);
+ return retval;
}
int rename_ref(const char *oldref, const char *newref, const char *logmsg)
int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
const char *newref, const char *logmsg)
{
- return refs->be->copy_ref(refs, oldref, newref, logmsg);
+ char *msg;
+ int retval;
+
+ msg = normalize_reflog_message(logmsg);
+ retval = refs->be->copy_ref(refs, oldref, newref, msg);
+ free(msg);
+ return retval;
}
int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)