summaryrefslogtreecommitdiff
path: root/refs/files-backend.c
Commit message (Collapse)AuthorAgeFilesLines
* files_transaction_finish(): delete reflogs before referencesmh/packed-ref-transactionsMichael Haggerty2017-09-091-14/+21
| | | | | | | | | If the deletion steps unexpectedly fail, it is less bad to leave a reference without its reflog than it is to leave a reflog without its reference, since the latter is an invalid repository state. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* files_ref_store: use a transaction to update packed refsMichael Haggerty2017-09-091-31/+101
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When processing a `files_ref_store` transaction, it is sometimes necessary to delete some references from the "packed-refs" file. Do that using a reference transaction conducted against the `packed_ref_store`. This change further decouples `files_ref_store` from `packed_ref_store`. It also fixes multiple problems, including the two revealed by test cases added in the previous commit. First, the old code didn't obtain the `packed-refs` lock until `files_transaction_finish()`. This means that a failure to acquire the `packed-refs` lock (e.g., due to contention with another process) wasn't detected until it was too late (problems like this are supposed to be detected in the "prepare" phase). The new code acquires the `packed-refs` lock in `files_transaction_prepare()`, the same stage of the processing when the loose reference locks are being acquired, removing another reason why the "prepare" phase might succeed and the "finish" phase might nevertheless fail. Second, the old code deleted the loose version of a reference before deleting any packed version of the same reference. This left a moment when another process might think that the packed version of the reference is current, which is incorrect. (Even worse, the packed version of the reference can be arbitrarily old, and might even point at an object that has since been garbage-collected.) Third, if a reference deletion fails to acquire the `packed-refs` lock altogether, then the old code might leave the repository in the incorrect state (possibly corrupt) described in the previous paragraph. Now we activate the new "packed-refs" file (sans any references that are being deleted) *before* deleting the corresponding loose references. But we hold the "packed-refs" lock until after the loose references have been finalized, thus preventing a simultaneous "pack-refs" process from packing the loose version of the reference in the time gap, which would otherwise defeat our attempt to delete it. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* files_initial_transaction_commit(): use a transaction for packed refsMichael Haggerty2017-09-091-10/+19
| | | | | | | | | | Use a `packed_ref_store` transaction in the implementation of `files_initial_transaction_commit()` rather than using internal features of the packed ref store. This further decouples `files_ref_store` from `packed_ref_store`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* prune_refs(): also free the linked listMichael Haggerty2017-09-091-4/+10
| | | | | | | | | At least since v1.7, the elements of the `refs_to_prune` linked list have been leaked. Fix the leak by teaching `prune_refs()` to free the list elements as it processes them. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* files_pack_refs(): use a reference transaction to write packed refsMichael Haggerty2017-09-091-7/+17
| | | | | | | | | | Now that the packed reference store supports transactions, we can use a transaction to write the packed versions of references that we want to pack. This decreases the coupling between `files_ref_store` and `packed_ref_store`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* packed_delete_refs(): implement methodMichael Haggerty2017-09-091-1/+1
| | | | | | | | | | Implement `packed_delete_refs()` using a reference transaction. This means that `files_delete_refs()` can use `refs_delete_refs()` instead of `repack_without_refs()` to delete any packed references, decreasing the coupling between the classes. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* Merge branch 'mh/ref-lock-entry'Junio C Hamano2017-08-261-2/+6
|\ | | | | | | | | | | | | | | | | | | | | The code to acquire a lock on a reference (e.g. while accepting a push from a client) used to immediately fail when the reference is already locked---now it waits for a very short while and retries, which can make it succeed if the lock holder was holding it during a read-only operation. * mh/ref-lock-entry: refs: retry acquiring reference locks for 100ms
| * refs: retry acquiring reference locks for 100msmh/ref-lock-entryMichael Haggerty2017-08-231-2/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The philosophy of reference locking has been, "if another process is changing a reference, then whatever I'm trying to do to it will probably fail anyway because my old-SHA-1 value is probably no longer current". But this argument falls down if the other process has locked the reference to do something that doesn't actually change the value of the reference, such as `pack-refs` or `reflog expire`. There actually *is* a decent chance that a planned reference update will still be able to go through after the other process has released the lock. So when trying to lock an individual reference (e.g., when creating "refs/heads/master.lock"), if it is already locked, then retry the lock acquisition for approximately 100 ms before giving up. This should eliminate some unnecessary lock conflicts without wasting a lot of time. Add a configuration setting, `core.filesRefLockTimeout`, to allow this setting to be tweaked. Note: the function `get_files_ref_lock_timeout_ms()` cannot be private to the files backend because it is also used by `write_pseudoref()` and `delete_pseudoref()`, which are defined in `refs.c` so that they can be used by other reference backends. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | Merge branch 'mh/packed-ref-store'Junio C Hamano2017-08-221-564/+75
|\ \ | |/ |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The "ref-store" code reorganization continues. * mh/packed-ref-store: (32 commits) files-backend: cheapen refname_available check when locking refs packed_ref_store: handle a packed-refs file that is a symlink read_packed_refs(): die if `packed-refs` contains bogus data t3210: add some tests of bogus packed-refs file contents repack_without_refs(): don't lock or unlock the packed refs commit_packed_refs(): remove call to `packed_refs_unlock()` clear_packed_ref_cache(): don't protest if the lock is held packed_refs_unlock(), packed_refs_is_locked(): new functions packed_refs_lock(): report errors via a `struct strbuf *err` packed_refs_lock(): function renamed from lock_packed_refs() commit_packed_refs(): use a staging file separate from the lockfile commit_packed_refs(): report errors rather than dying packed_ref_store: make class into a subclass of `ref_store` packed-backend: new module for handling packed references packed_read_raw_ref(): new function, replacing `resolve_packed_ref()` packed_ref_store: support iteration packed_peel_ref(): new function, extracted from `files_peel_ref()` repack_without_refs(): take a `packed_ref_store *` parameter get_packed_ref(): take a `packed_ref_store *` parameter rollback_packed_refs(): take a `packed_ref_store *` parameter ...
| * files-backend: cheapen refname_available check when locking refsmh/packed-ref-storeMichael Haggerty2017-08-171-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When locking references in preparation for updating them, we need to check that none of the newly added references D/F conflict with existing references (e.g., we don't allow `refs/foo` to be added if `refs/foo/bar` already exists, or vice versa). Prior to 524a9fdb51 (refs_verify_refname_available(): use function in more places, 2017-04-16), conflicts with existing loose references were checked by looking directly in the filesystem, and then conflicts with existing packed references were checked by running `verify_refname_available_dir()` against the packed-refs cache. But that commit changed the final check to call `refs_verify_refname_available()` against the *whole* files ref-store, including both loose and packed references, with the following comment: > This means that those callsites now check for conflicts with all > references rather than just packed refs, but the performance cost > shouldn't be significant (and will be regained later). That comment turned out to be too sanguine. User s@kazlauskas.me reported that fetches involving a very large number of references in neighboring directories were slowed down by that change. The problem is that when fetching, each reference is updated individually, within its own reference transaction. This is done because some reference updates might succeed even though others fail. But every time a reference update transaction is finished, `clear_loose_ref_cache()` is called. So when it is time to update the next reference, part of the loose ref cache has to be repopulated for the `refs_verify_refname_available()` call. If the references are all in neighboring directories, then the cost of repopulating the reference cache increases with the number of references, resulting in O(N²) effort. The comment above also claims that the performance cost "will be regained later". The idea was that once the packed-refs were finished being split out into a separate ref-store, we could limit the `refs_verify_refname_available()` call to the packed references again. That is what we do now. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * repack_without_refs(): don't lock or unlock the packed refsMichael Haggerty2017-07-031-16/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Change `repack_without_refs()` to expect the packed-refs lock to be held already, and not to release the lock before returning. Change the callers to deal with lock management. This change makes it possible for callers to hold the packed-refs lock for a longer span of time, a possibility that will eventually make it possible to fix some longstanding races. The only semantic change here is that `repack_without_refs()` used to forget to release the lock in the `if (!removed)` exit path. That omission is now fixed. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * commit_packed_refs(): remove call to `packed_refs_unlock()`Michael Haggerty2017-06-231-0/+2
| | | | | | | | | | | | | | | | Instead, change the callers of `commit_packed_refs()` to call `packed_refs_unlock()`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_refs_lock(): report errors via a `struct strbuf *err`Michael Haggerty2017-06-231-4/+2
| | | | | | | | | | | | | | | | That way the callers don't have to come up with error messages themselves. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_refs_lock(): function renamed from lock_packed_refs()Michael Haggerty2017-06-231-2/+2
| | | | | | | | | | | | | | | | | | Rename `lock_packed_refs()` to `packed_refs_lock()` for consistency with how other methods are named. Also, it's about to get some companions. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * commit_packed_refs(): report errors rather than dyingMichael Haggerty2017-06-231-5/+5
| | | | | | | | | | | | | | | | | | Report errors via a `struct strbuf *err` rather than by calling `die()`. To enable this goal, change `write_packed_entry()` to report errors via a return value and `errno` rather than dying. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_ref_store: make class into a subclass of `ref_store`Michael Haggerty2017-06-231-8/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add the infrastructure to make `packed_ref_store` implement `ref_store`, at least formally (few of the methods are actually implemented yet). Change the functions in its interface to take `ref_store *` arguments. Change `files_ref_store` to store a pointer to `ref_store *` and to call functions via the virtual `ref_store` interface where possible. This also means that a few `packed_ref_store` functions can become static. This is a work in progress. Some more `ref_store` methods will soon be implemented (e.g., those having to do with reference transactions). But some of them will never be implemented (e.g., those having to do with symrefs or reflogs). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed-backend: new module for handling packed referencesMichael Haggerty2017-06-231-639/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | Now that the interface between `files_ref_store` and `packed_ref_store` is relatively narrow, move the latter into a new module, "refs/packed-backend.h" and "refs/packed-backend.c". It still doesn't quite implement the `ref_store` interface, but it will soon. This commit moves code around and adjusts its visibility, but doesn't change anything. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_read_raw_ref(): new function, replacing `resolve_packed_ref()`Michael Haggerty2017-06-231-19/+17
| | | | | | | | | | | | | | | | Add a new function, `packed_read_raw_ref()`, which is nearly a `read_raw_ref_fn`. Use it in place of `resolve_packed_ref()`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_ref_store: support iterationMichael Haggerty2017-06-231-9/+110
| | | | | | | | | | | | | | | | | | | | Add the infrastructure to iterate over a `packed_ref_store`. It's a lot of boilerplate, but it's all part of a campaign to make `packed_ref_store` implement `ref_store`. In the future, this iterator will work much differently. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_peel_ref(): new function, extracted from `files_peel_ref()`Michael Haggerty2017-06-231-11/+15
| | | | | | | | | | | | | | This will later become a method of `packed_ref_store`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * repack_without_refs(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-10/+10
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * get_packed_ref(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-5/+7
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * rollback_packed_refs(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-8/+7
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * commit_packed_refs(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-9/+9
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * lock_packed_refs(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-9/+22
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * add_packed_ref(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-5/+5
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * get_packed_refs(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-5/+5
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * get_packed_ref_cache(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-14/+12
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * validate_packed_ref_cache(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-7/+6
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * clear_packed_ref_cache(): take a `packed_ref_store *` parameterMichael Haggerty2017-06-231-8/+8
| | | | | | | | | | | | | | It only cares about the packed-refs part of the reference store. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_ref_store: move `packed_refs_lock` member hereMichael Haggerty2017-06-231-15/+16
| | | | | | | | | | | | | | | | | | Move the `packed_refs_lock` member from `files_ref_store` to `packed_ref_store`, and rename it to `lock` since it's now more obvious what it is locking. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_ref_store: move `packed_refs_path` hereMichael Haggerty2017-06-231-13/+12
| | | | | | | | | | | | | | | | | | | | | | Move `packed_refs_path` from `files_ref_store` to `packed_ref_store`, and rename it to `path` since its meaning is clear from its new context. Inline `files_packed_refs_path()`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * packed_ref_store: new structMichael Haggerty2017-06-231-9/+33
| | | | | | | | | | | | | | | | | | Start extracting the packed-refs-related data structures into a new class, `packed_ref_store`. It doesn't yet implement `ref_store`, but it will. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * add_packed_ref(): teach function to overwrite existing refsMichael Haggerty2017-06-231-22/+18
| | | | | | | | | | | | | | | | | | | | | | Teach `add_packed_ref()` to overwrite an existing entry if one already exists for the specified `refname`. This means that we can call it from `files_pack_refs()`, thereby reducing the amount that the latter function needs to know about the internals of packed-reference handling. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | Merge branch 'mh/packed-ref-store-prep'Junio C Hamano2017-06-261-9/+23
|\ \ | |/ | | | | | | | | | | | | Bugfix for a topic that is (only) in 'master'. * mh/packed-ref-store-prep: for_each_bisect_ref(): don't trim refnames lock_packed_refs(): fix cache validity check
| * lock_packed_refs(): fix cache validity checkMichael Haggerty2017-06-121-9/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Commit 28ed9830b1 (get_packed_ref_cache(): assume "packed-refs" won't change while locked, 2017-05-22) assumes that the "packed-refs" file cannot change while we hold the lock. That assumption is justified *if* the lock has been held the whole time since the "packed-refs" file was last read. But in `lock_packed_refs()`, we ourselves lock the "packed-refs" file and then call `get_packed_ref_cache()` to ensure that the cache agrees with the file. The intent is to guard against the possibility that another process changed the "packed-refs" file the moment before we locked it. This check was defeated because `get_packed_ref_cache()` saw that the file was locked, and therefore didn't do the `stat_validity_check()` that we want. The mistake was compounded with a misleading comment in `lock_packed_refs()` claiming that it was doing the right thing. That comment came from an earlier draft of the mh/packed-ref-store-prep patch series when the commits were in a different order. So instead: * Extract a function `validate_packed_ref_cache()` that does the validity check independent of whether the lock is held. * Change `get_packed_ref_cache()` to call the new function, but only if the lock *isn't* held. * Change `lock_packed_refs()` to call the new function in any case before calling `get_packed_ref_cache()`. * Fix the comment in `lock_packed_refs()`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | Merge branch 'ab/free-and-null'Junio C Hamano2017-06-241-2/+1
|\ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A common pattern to free a piece of memory and assign NULL to the pointer that used to point at it has been replaced with a new FREE_AND_NULL() macro. * ab/free-and-null: *.[ch] refactoring: make use of the FREE_AND_NULL() macro coccinelle: make use of the "expression" FREE_AND_NULL() rule coccinelle: add a rule to make "expression" code use FREE_AND_NULL() coccinelle: make use of the "type" FREE_AND_NULL() rule coccinelle: add a rule to make "type" code use FREE_AND_NULL() git-compat-util: add a FREE_AND_NULL() wrapper around free(ptr); ptr = NULL
| * | coccinelle: make use of the "type" FREE_AND_NULL() ruleÆvar Arnfjörð Bjarmason2017-06-161-2/+1
| |/ | | | | | | | | | | | | | | | | | | Apply the result of the just-added coccinelle rule. This manually excludes a few occurrences, mostly things that resulted in many FREE_AND_NULL() on one line, that'll be manually fixed in a subsequent change. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | Merge branch 'bw/config-h'Junio C Hamano2017-06-241-0/+1
|\ \ | |/ |/| | | | | | | | | | | | | | | | | | | | | | | Fix configuration codepath to pay proper attention to commondir that is used in multi-worktree situation, and isolate config API into its own header file. * bw/config-h: config: don't implicitly use gitdir or commondir config: respect commondir setup: teach discover_git_directory to respect the commondir config: don't include config.h by default config: remove git_config_iter config: create config.h
| * config: don't include config.h by defaultBrandon Williams2017-06-151-0/+1
| | | | | | | | | | | | | | | | Stop including config.h by default in cache.h. Instead only include config.h in those files which require use of the config system. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | create_ref_entry(): remove `check_name` optionMichael Haggerty2017-05-231-4/+8
| | | | | | | | | | | | | | Only one caller was using it, so move the check to that caller. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | refs_ref_iterator_begin(): handle `GIT_REF_PARANOIA`Michael Haggerty2017-05-231-7/+4
| | | | | | | | | | | | | | | | | | Instead of handling `GIT_REF_PARANOIA` in `files_ref_iterator_begin()`, handle it in `refs_ref_iterator_begin()`, where it will cover all reference stores. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | read_packed_refs(): report unexpected fopen() failuresMichael Haggerty2017-05-231-2/+12
| | | | | | | | | | | | | | | | | | | | | | | | The old code ignored any errors encountered when trying to fopen the "packed-refs" file, treating all such failures as if the file didn't exist. But it could be that there is some other error opening the file (e.g., permissions problems), and we don't want to silently ignore such problems. So report any failures that are not due to ENOENT. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | read_packed_refs(): do more of the work of reading packed refsMichael Haggerty2017-05-231-16/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Teach `read_packed_refs()` to also * Allocate and initialize the new `packed_ref_cache` * Open and close the `packed-refs` file * Update the `validity` field of the new object This decreases the coupling between `packed_refs_cache` and `files_ref_store` by a little bit. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | get_packed_ref_cache(): assume "packed-refs" won't change while lockedMichael Haggerty2017-05-231-5/+11
| | | | | | | | | | | | | | | | If we've got the "packed-refs" file locked, then it can't change; there's no need to keep calling `stat_validity_check()` on it. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | should_pack_ref(): new function, extracted from `files_pack_refs()`Michael Haggerty2017-05-231-14/+28
| | | | | | | | | | | | | | | | | | Extract a function for deciding whether a reference should be packed. It is a self-contained bit of logic, so splitting it out improves readability. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | ref_update_reject_duplicates(): expose function to whole refs moduleMichael Haggerty2017-05-231-17/+0
| | | | | | | | | | | | | | It will soon have some other users. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | ref_transaction_prepare(): new optional step for reference updatesMichael Haggerty2017-05-231-13/+50
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the future, compound reference stores will sometimes need to modify references in two different reference stores at the same time, meaning that a single logical reference transaction might have to be implemented as two internal sub-transactions. They won't want to call `ref_transaction_commit()` for the two sub-transactions one after the other, because that wouldn't be atomic (the first commit could succeed and the second one fail). Instead, they will want to prepare both sub-transactions (i.e., obtain any necessary locks and do any pre-checks), and only if both prepare steps succeed, then commit both sub-transactions. Start preparing for that day by adding a new, optional `ref_transaction_prepare()` step to the reference transaction sequence, which obtains the locks and does any prechecks, reporting any errors that occur. Also add a `ref_transaction_abort()` function that can be used to abort a sub-transaction even if it has already been prepared. That is on the side of the public-facing API. On the side of the `ref_store` VTABLE, get rid of `transaction_commit` and instead add methods `transaction_prepare`, `transaction_finish`, and `transaction_abort`. A `ref_transaction_commit()` now basically calls methods `transaction_prepare` then `transaction_finish`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | ref_transaction_commit(): check for valid `transaction->state`Michael Haggerty2017-05-231-3/+0
| | | | | | | | | | | | | | | | | | Move the check that `transaction->state` is valid from `files_transaction_commit()` to `ref_transaction_commit()`, where other future reference backends can benefit from it as well. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | files_transaction_cleanup(): new helper functionMichael Haggerty2017-05-231-9/+24
| | | | | | | | | | | | | | | | | | | | | | Extract the cleanup functionality from `files_transaction_commit()` into a new function. It will soon have another caller. Use the common cleanup code even on early exit if the transaction is empty, to reduce code duplication. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>