467
return (entry->flag & REF_DIR) ? NULL : entry;
468
}
469
470
+/*
471
+ * Remove the entry with the given name from dir, recursing into
472
+ * subdirectories as necessary. If refname is the name of a directory
473
+ * (i.e., ends with '/'), then remove the directory and its contents.
474
+ * If the removal was successful, return the number of entries
475
+ * remaining in the directory entry that contained the deleted entry.
476
+ * If the name was not found, return -1. Please note that this
477
+ * function only deletes the entry from the cache; it does not delete
478
+ * it from the filesystem or ensure that other cache entries (which
479
+ * might be symbolic references to the removed entry) are updated.
480
+ * Nor does it remove any containing dir entries that might be made
481
+ * empty by the removal. dir must represent the top-level directory
482
+ * and must already be complete.
483
+ */
484
+static int remove_entry(struct ref_dir *dir, const char *refname)
485
+{
486
+ int refname_len = strlen(refname);
487
+ int entry_index;
488
+ struct ref_entry *entry;
489
+ int is_dir = refname[refname_len - 1] == '/';
490
+ if (is_dir) {
491
+ /*
492
+ * refname represents a reference directory. Remove
493
+ * the trailing slash; otherwise we will get the
494
+ * directory *representing* refname rather than the
495
+ * one *containing* it.
496
+ */
497
+ char *dirname = xmemdupz(refname, refname_len - 1);
498
+ dir = find_containing_dir(dir, dirname, 0);
499
+ free(dirname);
500
+ } else {
501
+ dir = find_containing_dir(dir, refname, 0);
502
+ }
503
+ if (!dir)
504
+ return -1;
505
+ entry_index = search_ref_dir(dir, refname, refname_len);
506
+ if (entry_index == -1)
507
+ return -1;
508
+ entry = dir->entries[entry_index];
509
+
510
+ memmove(&dir->entries[entry_index],
511
+ &dir->entries[entry_index + 1],
512
+ (dir->nr - entry_index - 1) * sizeof(*dir->entries)
513
+ );
514
+ dir->nr--;
515
+ if (dir->sorted > entry_index)
516
+ dir->sorted--;
517
+ free_ref_entry(entry);
518
+ return dir->nr;
519
+}
520
+
521
/*
522
* Add a ref_entry to the ref_dir (unsorted), recursing into
523
* subdirectories as necessary. dir must represent the top-level
1946
return lock_ref_sha1_basic(refname, old_sha1, flags, NULL);
1947
}
1948
1898
-struct repack_without_ref_sb {
1899
- const char *refname;
1900
- int fd;
1901
-};
1902
-
1903
-static int repack_without_ref_fn(struct ref_entry *entry, void *cb_data)
1949
+static int repack_ref_fn(struct ref_entry *entry, void *cb_data)
1950
{
1905
- struct repack_without_ref_sb *data = cb_data;
1951
+ int *fd = cb_data;
1952
char line[PATH_MAX + 100];
1953
int len;
1954
1909
- if (!strcmp(data->refname, entry->name))
1910
- return 0;
1955
if (entry->flag & REF_ISBROKEN) {
1956
/* This shouldn't happen to packed refs. */
1957
error("%s is broken!", entry->name);
1992
/* this should not happen but just being defensive */
1993
if (len > sizeof(line))
1994
die("too long a refname '%s'", entry->name);
1951
- write_or_die(data->fd, line, len);
1995
+ write_or_die(*fd, line, len);
1996
return 0;
1997
}
1998
2000
2001
static int repack_without_ref(const char *refname)
2002
{
1959
- struct repack_without_ref_sb data;
2003
+ int fd;
2004
struct ref_cache *refs = get_ref_cache(NULL);
2005
struct ref_dir *packed;
2006
2007
if (!get_packed_ref(refname))
2008
return 0; /* refname does not exist in packed refs */
2009
1966
- data.refname = refname;
1967
- data.fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
1968
- if (data.fd < 0) {
2010
+ fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
2011
+ if (fd < 0) {
2012
unable_to_lock_error(git_path("packed-refs"), errno);
2013
return error("cannot delete '%s' from packed refs", refname);
2014
}
2015
clear_packed_ref_cache(refs);
2016
packed = get_packed_refs(refs);
1974
- do_for_each_entry_in_dir(packed, 0, repack_without_ref_fn, &data);
2017
+ /* Remove refname from the cache. */
2018
+ if (remove_entry(packed, refname) == -1) {
2019
+ /*
2020
+ * The packed entry disappeared while we were
2021
+ * acquiring the lock.
2022
+ */
2023
+ rollback_lock_file(&packlock);
2024
+ return 0;
2025
+ }
2026
+ do_for_each_entry_in_dir(packed, 0, repack_ref_fn, &fd);
2027
return commit_lock_file(&packlock);
2028
}
2029
2052
ret |= repack_without_ref(lock->ref_name);
2053
2054
unlink_or_warn(git_path("logs/%s", lock->ref_name));
2003
- invalidate_ref_cache(NULL);
2055
+ clear_loose_ref_cache(get_ref_cache(NULL));
2056
unlock_ref(lock);
2057
return ret;
2058
}