The question raised in this PR is using long git commit hashes and short git commit hashes.
The format of the HEAD-versions we use is the following: HEAD-<version>_<revision>
, where version is a commit hash. There are plenty of download strategies, but I refer only to GitDownloadStrategy
here, because others have either other 'commit' structure or no short-hashes support.
To compare two HEAD version we need to compare commit hashes. And this is what this PR is about. Suppose we only store long hashes. So, to detect if installed HEAD-version is outdated we need to compare upstream hash of the project with hash used in installed HEAD-version prefix. If they are the same, then installed HEAD is up-to-date, otherwise we have outdated HEAD.
Let's now suppose we use short hashes. What we do to detect outdated versions is a) calling VCSDownloadStrategy#last_commit
which goes to cached location and gets the hash and b) compare returned last_commit
with HEAD-prefix. If it any time last_commit
increases its length, then installed HEAD-prefix cannot be equal to it anymore, thus, it's outdated.
More precisely:
$ ls /usr/local/Cellar/ack
HEAD-a0a0a0a
==> Interactive Homebrew Shell
Example commands available with: brew irb --examples
2.0.0-p481 :001 > downloader = Formulary.factory("ack").head.downloader
=> ...
2.0.0-p481 :002 > downloader.shutup!
=> "true"
2.0.0-p481 :003 > downloader.fetch_last_commit
=> "a0a0a0a0"
2.0.0-p481 :004 > ^D
That means that a0a0a0a
is no longer unique within the repo, but it was when we installed HEAD-a0a0a0a
, therefore HEAD is outdated.
The problem arises when we introduce GitGitHubDownloadStrategy
to be able to detect outdated versions without fetching a repository. GitGitHubDownloadStrategy#last_commit
returns full-length hash. The problem is that we can't check installed hash and fetched hash for equality anymore. What we can is to perform start_with?
check, but it still can't guarantee the version is up-to-date.
Example:
$ ls $(brew --cellar)/ack
HEAD-b090608c
Let's now suppose we want to check if HEAD-b09060c
is outdated
using GitHub API, which return full-length prefix and let's
suppose it returns the following hash:
b090608c49643099a47247d79ac9ca80d05c2ee0
How do we treat it? Is the HEAD version outdated or not? Suppose it's not since prefixes are the same. After a while we check it again and GitHub API returns the following hash:
b090608c00000000000000000000000000000000
So, we still think our installed HEAD is up-to-date, however that's not true.
- Store long hashes in Tab. Cons: complicate.
- Use short commits and use
==
forVCSDownloadStrategy
andstart_with?
forGitHubDownloadStrategy
. Cons: there is a possibility we get outdated version (see the example). - Store long hashes everywhere. Cons: long hashes in
outdated
outputs and long prefixes.
For now long hashes used everywhere in the code and even if we use short hashes for git we cannot escape from long hashes for other VCSs.
CC @xu-cheng