git/refs/files-backend.c

#define USE_THE_REPOSITORY_VARIABLE

#include "../git-compat-util.h"
#include "../config.h"
#include "../copy.h"
#include "../environment.h"
#include "../gettext.h"
#include "../hash.h"
#include "../hex.h"
#include "../fsck.h"
#include "../refs.h"
#include "../repo-settings.h"
#include "refs-internal.h"
#include "ref-cache.h"
#include "packed-backend.h"
#include "../ident.h"
#include "../iterator.h"
#include "../dir-iterator.h"
#include "../lockfile.h"
#include "../object.h"
#include "../object-file.h"
#include "../path.h"
#include "../dir.h"
#include "../chdir-notify.h"
#include "../setup.h"
#include "../wrapper.h"
#include "../write-or-die.h"
#include "../revision.h"
#include <wildmatch.h>

/*
 * This backend uses the following flags in `ref_update::flags` for
 * internal bookkeeping purposes. Their numerical values must not
 * conflict with REF_NO_DEREF, REF_FORCE_CREATE_REFLOG, REF_HAVE_NEW,
 * or REF_HAVE_OLD, which are also stored in `ref_update::flags`.
 */

/*
 * Used as a flag in ref_update::flags when a loose ref is being
 * pruned. This flag must only be used when REF_NO_DEREF is set.
 */
#define REF_IS_PRUNING

/*
 * Flag passed to lock_ref_sha1_basic() telling it to tolerate broken
 * refs (i.e., because the reference is about to be deleted anyway).
 */
#define REF_DELETING

/*
 * Used as a flag in ref_update::flags when the lockfile needs to be
 * committed.
 */
#define REF_NEEDS_COMMIT

/*
 * Used as a flag in ref_update::flags when the ref_update was via an
 * update to HEAD.
 */
#define REF_UPDATE_VIA_HEAD

/*
 * Used as a flag in ref_update::flags when a reference has been
 * deleted and the ref's parent directories may need cleanup.
 */
#define REF_DELETED_RMDIR

struct ref_lock {};

struct files_ref_store {};

static void clear_loose_ref_cache(struct files_ref_store *refs)
{}

/*
 * Create a new submodule ref cache and add it to the internal
 * set of caches.
 */
static struct ref_store *files_ref_store_init(struct repository *repo,
					      const char *gitdir,
					      unsigned int flags)
{}

/*
 * Die if refs is not the main ref store. caller is used in any
 * necessary error messages.
 */
static void files_assert_main_repository(struct files_ref_store *refs,
					 const char *caller)
{}

/*
 * Downcast ref_store to files_ref_store. Die if ref_store is not a
 * files_ref_store. required_flags is compared with ref_store's
 * store_flags to ensure the ref_store has all required capabilities.
 * "caller" is used in any necessary error messages.
 */
static struct files_ref_store *files_downcast(struct ref_store *ref_store,
					      unsigned int required_flags,
					      const char *caller)
{}

static void files_ref_store_release(struct ref_store *ref_store)
{}

static void files_reflog_path(struct files_ref_store *refs,
			      struct strbuf *sb,
			      const char *refname)
{}

static void files_ref_path(struct files_ref_store *refs,
			   struct strbuf *sb,
			   const char *refname)
{}

/*
 * Manually add refs/bisect, refs/rewritten and refs/worktree, which, being
 * per-worktree, might not appear in the directory listing for
 * refs/ in the main repo.
 */
static void add_per_worktree_entries_to_dir(struct ref_dir *dir, const char *dirname)
{}

static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
					    const char *refname,
					    struct ref_dir *dir)
{}

/*
 * Read the loose references from the namespace dirname into dir
 * (without recursing).  dirname must end with '/'.  dir must be the
 * directory entry corresponding to dirname.
 */
static void loose_fill_ref_dir(struct ref_store *ref_store,
			       struct ref_dir *dir, const char *dirname)
{}

static int for_each_root_ref(struct files_ref_store *refs,
			     int (*cb)(const char *refname, void *cb_data),
			     void *cb_data)
{}

struct fill_root_ref_data {};

static int fill_root_ref(const char *refname, void *cb_data)
{}

/*
 * Add root refs to the ref dir by parsing the directory for any files which
 * follow the root ref syntax.
 */
static void add_root_refs(struct files_ref_store *refs,
			  struct ref_dir *dir)
{}

static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs,
					     unsigned int flags)
{}

static int read_ref_internal(struct ref_store *ref_store, const char *refname,
			     struct object_id *oid, struct strbuf *referent,
			     unsigned int *type, int *failure_errno, int skip_packed_refs)
{}

static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
			      struct object_id *oid, struct strbuf *referent,
			      unsigned int *type, int *failure_errno)
{}

static int files_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
				   struct strbuf *referent)
{}

int parse_loose_ref_contents(const struct git_hash_algo *algop,
			     const char *buf, struct object_id *oid,
			     struct strbuf *referent, unsigned int *type,
			     int *failure_errno)
{}

static void unlock_ref(struct ref_lock *lock)
{}

/*
 * Lock refname, without following symrefs, and set *lock_p to point
 * at a newly-allocated lock object. Fill in lock->old_oid, referent,
 * and type similarly to read_raw_ref().
 *
 * The caller must verify that refname is a "safe" reference name (in
 * the sense of refname_is_safe()) before calling this function.
 *
 * If the reference doesn't already exist, verify that refname doesn't
 * have a D/F conflict with any existing references. extras and skip
 * are passed to refs_verify_refname_available() for this check.
 *
 * If mustexist is not set and the reference is not found or is
 * broken, lock the reference anyway but clear old_oid.
 *
 * Return 0 on success. On failure, write an error message to err and
 * return TRANSACTION_NAME_CONFLICT or TRANSACTION_GENERIC_ERROR.
 *
 * Implementation note: This function is basically
 *
 *     lock reference
 *     read_raw_ref()
 *
 * but it includes a lot more code to
 * - Deal with possible races with other processes
 * - Avoid calling refs_verify_refname_available() when it can be
 *   avoided, namely if we were successfully able to read the ref
 * - Generate informative error messages in the case of failure
 */
static int lock_raw_ref(struct files_ref_store *refs,
			const char *refname, int mustexist,
			const struct string_list *extras,
			struct ref_lock **lock_p,
			struct strbuf *referent,
			unsigned int *type,
			struct strbuf *err)
{}

struct files_ref_iterator {};

static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
{}

static int files_ref_iterator_peel(struct ref_iterator *ref_iterator,
				   struct object_id *peeled)
{}

static int files_ref_iterator_abort(struct ref_iterator *ref_iterator)
{}

static struct ref_iterator_vtable files_ref_iterator_vtable =;

static struct ref_iterator *files_ref_iterator_begin(
		struct ref_store *ref_store,
		const char *prefix, const char **exclude_patterns,
		unsigned int flags)
{}

/*
 * Callback function for raceproof_create_file(). This function is
 * expected to do something that makes dirname(path) permanent despite
 * the fact that other processes might be cleaning up empty
 * directories at the same time. Usually it will create a file named
 * path, but alternatively it could create another file in that
 * directory, or even chdir() into that directory. The function should
 * return 0 if the action was completed successfully. On error, it
 * should return a nonzero result and set errno.
 * raceproof_create_file() treats two errno values specially:
 *
 * - ENOENT -- dirname(path) does not exist. In this case,
 *             raceproof_create_file() tries creating dirname(path)
 *             (and any parent directories, if necessary) and calls
 *             the function again.
 *
 * - EISDIR -- the file already exists and is a directory. In this
 *             case, raceproof_create_file() removes the directory if
 *             it is empty (and recursively any empty directories that
 *             it contains) and calls the function again.
 *
 * Any other errno causes raceproof_create_file() to fail with the
 * callback's return value and errno.
 *
 * Obviously, this function should be OK with being called again if it
 * fails with ENOENT or EISDIR. In other scenarios it will not be
 * called again.
 */
create_file_fn;

/*
 * Create a file in dirname(path) by calling fn, creating leading
 * directories if necessary. Retry a few times in case we are racing
 * with another process that is trying to clean up the directory that
 * contains path. See the documentation for create_file_fn for more
 * details.
 *
 * Return the value and set the errno that resulted from the most
 * recent call of fn. fn is always called at least once, and will be
 * called more than once if it returns ENOENT or EISDIR.
 */
static int raceproof_create_file(const char *path, create_file_fn fn, void *cb)
{}

static int remove_empty_directories(struct strbuf *path)
{}

static int create_reflock(const char *path, void *cb)
{}

/*
 * Locks a ref returning the lock on success and NULL on failure.
 */
static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
					   const char *refname,
					   struct strbuf *err)
{}

struct ref_to_prune {};

enum {};

/*
 * Remove empty parent directories associated with the specified
 * reference and/or its reflog, but spare [logs/]refs/ and immediate
 * subdirs. flags is a combination of REMOVE_EMPTY_PARENTS_REF and/or
 * REMOVE_EMPTY_PARENTS_REFLOG.
 */
static void try_remove_empty_parents(struct files_ref_store *refs,
				     const char *refname,
				     unsigned int flags)
{}

/* make sure nobody touched the ref, and unlink */
static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
{}

/*
 * Prune the loose versions of the references in the linked list
 * `*refs_to_prune`, freeing the entries in the list as we go.
 */
static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_to_prune)
{}

/*
 * Return true if the specified reference should be packed.
 */
static int should_pack_ref(struct files_ref_store *refs,
			   const char *refname,
			   const struct object_id *oid, unsigned int ref_flags,
			   struct pack_refs_opts *opts)
{}

static int should_pack_refs(struct files_ref_store *refs,
			    struct pack_refs_opts *opts)
{}

static int files_pack_refs(struct ref_store *ref_store,
			   struct pack_refs_opts *opts)
{}

/*
 * People using contrib's git-new-workdir have .git/logs/refs ->
 * /some/other/path/.git/logs/refs, and that may live on another device.
 *
 * IOW, to avoid cross device rename errors, the temporary renamed log must
 * live into logs/refs.
 */
#define TMP_RENAMED_LOG

struct rename_cb {};

static int rename_tmp_log_callback(const char *path, void *cb_data)
{}

static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname)
{}

static int write_ref_to_lockfile(struct files_ref_store *refs,
				 struct ref_lock *lock,
				 const struct object_id *oid,
				 int skip_oid_verification, struct strbuf *err);
static int commit_ref_update(struct files_ref_store *refs,
			     struct ref_lock *lock,
			     const struct object_id *oid, const char *logmsg,
			     int flags,
			     struct strbuf *err);

/*
 * Emit a better error message than lockfile.c's
 * unable_to_lock_message() would in case there is a D/F conflict with
 * another existing reference. If there would be a conflict, emit an error
 * message and return false; otherwise, return true.
 *
 * Note that this function is not safe against all races with other
 * processes, and that's not its job. We'll emit a more verbose error on D/f
 * conflicts if we get past it into lock_ref_oid_basic().
 */
static int refs_rename_ref_available(struct ref_store *refs,
			      const char *old_refname,
			      const char *new_refname)
{}

static int files_copy_or_rename_ref(struct ref_store *ref_store,
			    const char *oldrefname, const char *newrefname,
			    const char *logmsg, int copy)
{}

static int files_rename_ref(struct ref_store *ref_store,
			    const char *oldrefname, const char *newrefname,
			    const char *logmsg)
{}

static int files_copy_ref(struct ref_store *ref_store,
			    const char *oldrefname, const char *newrefname,
			    const char *logmsg)
{}

static int close_ref_gently(struct ref_lock *lock)
{}

static int commit_ref(struct ref_lock *lock)
{}

static int open_or_create_logfile(const char *path, void *cb)
{}

/*
 * Create a reflog for a ref. If force_create = 0, only create the
 * reflog for certain refs (those for which should_autocreate_reflog
 * returns non-zero). Otherwise, create it regardless of the reference
 * name. If the logfile already existed or was created, return 0 and
 * set *logfd to the file descriptor opened for appending to the file.
 * If no logfile exists and we decided not to create one, return 0 and
 * set *logfd to -1. On failure, fill in *err, set *logfd to -1, and
 * return -1.
 */
static int log_ref_setup(struct files_ref_store *refs,
			 const char *refname, int force_create,
			 int *logfd, struct strbuf *err)
{}

static int files_create_reflog(struct ref_store *ref_store, const char *refname,
			       struct strbuf *err)
{}

static int log_ref_write_fd(int fd, const struct object_id *old_oid,
			    const struct object_id *new_oid,
			    const char *committer, const char *msg)
{}

static int files_log_ref_write(struct files_ref_store *refs,
			       const char *refname, const struct object_id *old_oid,
			       const struct object_id *new_oid, const char *msg,
			       int flags, struct strbuf *err)
{}

/*
 * Write oid into the open lockfile, then close the lockfile. On
 * errors, rollback the lockfile, fill in *err and return -1.
 */
static int write_ref_to_lockfile(struct files_ref_store *refs,
				 struct ref_lock *lock,
				 const struct object_id *oid,
				 int skip_oid_verification, struct strbuf *err)
{}

/*
 * Commit a change to a loose reference that has already been written
 * to the loose reference lockfile. Also update the reflogs if
 * necessary, using the specified lockmsg (which can be NULL).
 */
static int commit_ref_update(struct files_ref_store *refs,
			     struct ref_lock *lock,
			     const struct object_id *oid, const char *logmsg,
			     int flags,
			     struct strbuf *err)
{}

#ifdef NO_SYMLINK_HEAD
#define create_ref_symlink
#else
static int create_ref_symlink(struct ref_lock *lock, const char *target)
{}
#endif

static int create_symref_lock(struct ref_lock *lock, const char *target,
			      struct strbuf *err)
{}

static int files_reflog_exists(struct ref_store *ref_store,
			       const char *refname)
{}

static int files_delete_reflog(struct ref_store *ref_store,
			       const char *refname)
{}

static int show_one_reflog_ent(struct files_ref_store *refs, struct strbuf *sb,
			       each_reflog_ent_fn fn, void *cb_data)
{}

static char *find_beginning_of_line(char *bob, char *scan)
{}

static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
					     const char *refname,
					     each_reflog_ent_fn fn,
					     void *cb_data)
{}

static int files_for_each_reflog_ent(struct ref_store *ref_store,
				     const char *refname,
				     each_reflog_ent_fn fn, void *cb_data)
{}

struct files_reflog_iterator {};

static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
{}

static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
				      struct object_id *peeled UNUSED)
{}

static int files_reflog_iterator_abort(struct ref_iterator *ref_iterator)
{}

static struct ref_iterator_vtable files_reflog_iterator_vtable =;

static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store,
						  const char *gitdir)
{}

static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
{}

/*
 * If update is a direct update of head_ref (the reference pointed to
 * by HEAD), then add an extra REF_LOG_ONLY update for HEAD.
 */
static int split_head_update(struct ref_update *update,
			     struct ref_transaction *transaction,
			     const char *head_ref,
			     struct string_list *affected_refnames,
			     struct strbuf *err)
{}

/*
 * update is for a symref that points at referent and doesn't have
 * REF_NO_DEREF set. Split it into two updates:
 * - The original update, but with REF_LOG_ONLY and REF_NO_DEREF set
 * - A new, separate update for the referent reference
 * Note that the new update will itself be subject to splitting when
 * the iteration gets to it.
 */
static int split_symref_update(struct ref_update *update,
			       const char *referent,
			       struct ref_transaction *transaction,
			       struct string_list *affected_refnames,
			       struct strbuf *err)
{}

/*
 * Check whether the REF_HAVE_OLD and old_oid values stored in update
 * are consistent with oid, which is the reference's current value. If
 * everything is OK, return 0; otherwise, write an error message to
 * err and return -1.
 */
static int check_old_oid(struct ref_update *update, struct object_id *oid,
			 struct strbuf *err)
{}

/*
 * Prepare for carrying out update:
 * - Lock the reference referred to by update.
 * - Read the reference under lock.
 * - Check that its old OID value (if specified) is correct, and in
 *   any case record it in update->lock->old_oid for later use when
 *   writing the reflog.
 * - If it is a symref update without REF_NO_DEREF, split it up into a
 *   REF_LOG_ONLY update of the symref and add a separate update for
 *   the referent to transaction.
 * - If it is an update of head_ref, add a corresponding REF_LOG_ONLY
 *   update of HEAD.
 */
static int lock_ref_for_update(struct files_ref_store *refs,
			       struct ref_update *update,
			       struct ref_transaction *transaction,
			       const char *head_ref,
			       struct string_list *affected_refnames,
			       struct strbuf *err)
{}

struct files_transaction_backend_data {};

/*
 * Unlock any references in `transaction` that are still locked, and
 * mark the transaction closed.
 */
static void files_transaction_cleanup(struct files_ref_store *refs,
				      struct ref_transaction *transaction)
{}

static int files_transaction_prepare(struct ref_store *ref_store,
				     struct ref_transaction *transaction,
				     struct strbuf *err)
{}

static int parse_and_write_reflog(struct files_ref_store *refs,
				  struct ref_update *update,
				  struct ref_lock *lock,
				  struct strbuf *err)
{}

static int files_transaction_finish(struct ref_store *ref_store,
				    struct ref_transaction *transaction,
				    struct strbuf *err)
{}

static int files_transaction_abort(struct ref_store *ref_store,
				   struct ref_transaction *transaction,
				   struct strbuf *err UNUSED)
{}

static int ref_present(const char *refname, const char *referent UNUSED,
		       const struct object_id *oid UNUSED,
		       int flags UNUSED,
		       void *cb_data)
{}

static int files_initial_transaction_commit(struct ref_store *ref_store,
					    struct ref_transaction *transaction,
					    struct strbuf *err)
{}

struct expire_reflog_cb {};

static int expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
			     const char *email, timestamp_t timestamp, int tz,
			     const char *message, void *cb_data)
{}

static int files_reflog_expire(struct ref_store *ref_store,
			       const char *refname,
			       unsigned int expire_flags,
			       reflog_expiry_prepare_fn prepare_fn,
			       reflog_expiry_should_prune_fn should_prune_fn,
			       reflog_expiry_cleanup_fn cleanup_fn,
			       void *policy_cb_data)
{}

static int files_ref_store_create_on_disk(struct ref_store *ref_store,
					  int flags,
					  struct strbuf *err UNUSED)
{}

struct remove_one_root_ref_data {};

static int remove_one_root_ref(const char *refname,
			       void *cb_data)
{}

static int files_ref_store_remove_on_disk(struct ref_store *ref_store,
					  struct strbuf *err)
{}

/*
 * For refs and reflogs, they share a unified interface when scanning
 * the whole directory. This function is used as the callback for each
 * regular file or symlink in the directory.
 */
files_fsck_refs_fn;

static int files_fsck_refs_name(struct ref_store *ref_store UNUSED,
				struct fsck_options *o,
				const char *refs_check_dir,
				struct dir_iterator *iter)
{}

static int files_fsck_refs_dir(struct ref_store *ref_store,
			       struct fsck_options *o,
			       const char *refs_check_dir,
			       files_fsck_refs_fn *fsck_refs_fn)
{}

static int files_fsck_refs(struct ref_store *ref_store,
			   struct fsck_options *o)
{}

static int files_fsck(struct ref_store *ref_store,
		      struct fsck_options *o)
{}

struct ref_storage_be refs_be_files =;