aboutsummaryrefslogtreecommitdiff
path: root/refs
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2017-10-03 15:42:48 +0900
committerJunio C Hamano <gitster@pobox.com>2017-10-03 15:42:48 +0900
commit3b48045c6c73a51834a2f83440a30225485ee431 (patch)
treeca7e9460aaadd4e6f26414c86bd72df6ab371fb8 /refs
parentb2a2c4d8099c69ec997e51cac489c0947ad17956 (diff)
parente5435ff1fc64d93cce73ec4ee2571219384a92a9 (diff)
downloadgit-3b48045c6c73a51834a2f83440a30225485ee431.tar.gz
git-3b48045c6c73a51834a2f83440a30225485ee431.tar.xz
Merge branch 'sd/branch-copy'
"git branch" learned "-c/-C" to create a new branch by copying an existing one. * sd/branch-copy: branch: fix "copy" to never touch HEAD branch: add a --copy (-c) option to go with --move (-m) branch: add test for -m renaming multiple config sections config: create a function to format section headers
Diffstat (limited to 'refs')
-rw-r--r--refs/files-backend.c46
-rw-r--r--refs/packed-backend.c8
-rw-r--r--refs/refs-internal.h4
3 files changed, 50 insertions, 8 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c
index fec77744b..38d16a13a 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1258,9 +1258,9 @@ static int commit_ref_update(struct files_ref_store *refs,
const struct object_id *oid, const char *logmsg,
struct strbuf *err);
-static int files_rename_ref(struct ref_store *ref_store,
+static int files_copy_or_rename_ref(struct ref_store *ref_store,
const char *oldrefname, const char *newrefname,
- const char *logmsg)
+ const char *logmsg, int copy)
{
struct files_ref_store *refs =
files_downcast(ref_store, REF_STORE_WRITE, "rename_ref");
@@ -1292,8 +1292,12 @@ static int files_rename_ref(struct ref_store *ref_store,
}
if (flag & REF_ISSYMREF) {
- ret = error("refname %s is a symbolic ref, renaming it is not supported",
- oldrefname);
+ if (copy)
+ ret = error("refname %s is a symbolic ref, copying it is not supported",
+ oldrefname);
+ else
+ ret = error("refname %s is a symbolic ref, renaming it is not supported",
+ oldrefname);
goto out;
}
if (!refs_rename_ref_available(&refs->base, oldrefname, newrefname)) {
@@ -1301,13 +1305,19 @@ static int files_rename_ref(struct ref_store *ref_store,
goto out;
}
- if (log && rename(sb_oldref.buf, tmp_renamed_log.buf)) {
+ if (!copy && log && rename(sb_oldref.buf, tmp_renamed_log.buf)) {
ret = error("unable to move logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
oldrefname, strerror(errno));
goto out;
}
- if (refs_delete_ref(&refs->base, logmsg, oldrefname,
+ if (copy && log && copy_file(tmp_renamed_log.buf, sb_oldref.buf, 0644)) {
+ ret = error("unable to copy logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
+ oldrefname, strerror(errno));
+ goto out;
+ }
+
+ if (!copy && refs_delete_ref(&refs->base, logmsg, oldrefname,
orig_oid.hash, REF_NODEREF)) {
error("unable to delete old %s", oldrefname);
goto rollback;
@@ -1320,7 +1330,7 @@ static int files_rename_ref(struct ref_store *ref_store,
* the safety anyway; we want to delete the reference whatever
* its current value.
*/
- if (!refs_read_ref_full(&refs->base, newrefname,
+ if (!copy && !refs_read_ref_full(&refs->base, newrefname,
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
oid.hash, NULL) &&
refs_delete_ref(&refs->base, NULL, newrefname,
@@ -1351,7 +1361,10 @@ static int files_rename_ref(struct ref_store *ref_store,
lock = lock_ref_sha1_basic(refs, newrefname, NULL, NULL, NULL,
REF_NODEREF, NULL, &err);
if (!lock) {
- error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
+ if (copy)
+ error("unable to copy '%s' to '%s': %s", oldrefname, newrefname, err.buf);
+ else
+ error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
strbuf_release(&err);
goto rollback;
}
@@ -1402,6 +1415,22 @@ static int files_rename_ref(struct ref_store *ref_store,
return ret;
}
+static int files_rename_ref(struct ref_store *ref_store,
+ const char *oldrefname, const char *newrefname,
+ const char *logmsg)
+{
+ return files_copy_or_rename_ref(ref_store, oldrefname,
+ newrefname, logmsg, 0);
+}
+
+static int files_copy_ref(struct ref_store *ref_store,
+ const char *oldrefname, const char *newrefname,
+ const char *logmsg)
+{
+ return files_copy_or_rename_ref(ref_store, oldrefname,
+ newrefname, logmsg, 1);
+}
+
static int close_ref_gently(struct ref_lock *lock)
{
if (close_lock_file_gently(&lock->lk))
@@ -3064,6 +3093,7 @@ struct ref_storage_be refs_be_files = {
files_create_symref,
files_delete_refs,
files_rename_ref,
+ files_copy_ref,
files_ref_iterator_begin,
files_read_raw_ref,
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 3bc47ffd5..9c0d685c7 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -966,6 +966,13 @@ static int packed_rename_ref(struct ref_store *ref_store,
die("BUG: packed reference store does not support renaming references");
}
+static int packed_copy_ref(struct ref_store *ref_store,
+ const char *oldrefname, const char *newrefname,
+ const char *logmsg)
+{
+ die("BUG: packed reference store does not support copying references");
+}
+
static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store)
{
return empty_ref_iterator_begin();
@@ -1031,6 +1038,7 @@ struct ref_storage_be refs_be_packed = {
packed_create_symref,
packed_delete_refs,
packed_rename_ref,
+ packed_copy_ref,
packed_ref_iterator_begin,
packed_read_raw_ref,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index d7d344de7..8821e27ed 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -559,6 +559,9 @@ typedef int delete_refs_fn(struct ref_store *ref_store, const char *msg,
typedef int rename_ref_fn(struct ref_store *ref_store,
const char *oldref, const char *newref,
const char *logmsg);
+typedef int copy_ref_fn(struct ref_store *ref_store,
+ const char *oldref, const char *newref,
+ const char *logmsg);
/*
* Iterate over the references in `ref_store` whose names start with
@@ -657,6 +660,7 @@ struct ref_storage_be {
create_symref_fn *create_symref;
delete_refs_fn *delete_refs;
rename_ref_fn *rename_ref;
+ copy_ref_fn *copy_ref;
ref_iterator_begin_fn *iterator_begin;
read_raw_ref_fn *read_raw_ref;