aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
authorMartin Afanasjew2016-05-31 17:11:57 +0200
committerMartin Afanasjew2016-05-31 17:11:57 +0200
commitb9552a5fbf3772b408cdb25c3a545bb1444ba8ff (patch)
tree9e5f96a4f531428c9cbce65e1283c556465abe65 /Library
parent0a7fcf29797469f7cd9eaa653ba3e54e412e4583 (diff)
downloadbrew-b9552a5fbf3772b408cdb25c3a545bb1444ba8ff.tar.bz2
download_strategy: fix git submodule references (#303)
Some Git versions create absolute `gitdir:` pointers in a submodule's `.git` file, which can be problematic once the resource is staged and causes various Git operations for those submodules to fail. Work around this issue by fixing the submodule `.git` files after submodule update. See Homebrew/homebrew-core#1520 for details and an affected formula.
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/download_strategy.rb33
1 files changed, 33 insertions, 0 deletions
diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index bd12524fa..19ce95b48 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -696,6 +696,39 @@ class GitDownloadStrategy < VCSDownloadStrategy
def update_submodules
quiet_safe_system "git", "submodule", "foreach", "--recursive", "git submodule sync"
quiet_safe_system "git", "submodule", "update", "--init", "--recursive"
+ fix_absolute_submodule_gitdir_references!
+ end
+
+ def fix_absolute_submodule_gitdir_references!
+ # When checking out Git repositories with recursive submodules, some Git
+ # versions create `.git` files with absolute instead of relative `gitdir:`
+ # pointers. This works for the cached location, but breaks various Git
+ # operations once the affected Git resource is staged, i.e. recursively
+ # copied to a new location. (This bug was introduced in Git 2.7.0 and fixed
+ # in 2.8.3. Clones created with affected version remain broken.)
+ # See https://github.com/Homebrew/homebrew-core/pull/1520 for an example.
+ submodule_dirs = Utils.popen_read(
+ "git", "submodule", "--quiet", "foreach", "--recursive", "pwd")
+ submodule_dirs.lines.map(&:chomp).each do |submodule_dir|
+ work_dir = Pathname.new(submodule_dir)
+
+ # Only check and fix if `.git` is a regular file, not a directory.
+ dot_git = work_dir/".git"
+ next unless dot_git.file?
+
+ git_dir = dot_git.read.chomp[/^gitdir: (.*)$/, 1]
+ if git_dir.nil?
+ onoe "Failed to parse '#{dot_git}'." if ARGV.homebrew_developer?
+ next
+ end
+
+ # Only attempt to fix absolute paths.
+ next unless git_dir.start_with?("/")
+
+ # Make the `gitdir:` reference relative to the working directory.
+ relative_git_dir = Pathname.new(git_dir).relative_path_from(work_dir)
+ dot_git.atomic_write("gitdir: #{relative_git_dir}\n")
+ end
end
end