forked from cristibalan/braid
/
update.rb
112 lines (95 loc) · 3.73 KB
/
update.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module Braid
module Commands
class Update < Command
def run(path, options = {})
bail_on_local_changes!
with_reset_on_error do
path ? update_one(path, options) : update_all(options)
end
end
protected
def update_all(options = {})
options.reject! { |k,v| %w(revision head).include?(k) }
msg "Updating all mirrors."
config.mirrors.each do |path|
update_one(path, options)
end
end
def update_one(path, options = {})
mirror = config.get!(path)
revision_message = options["revision"] ? " to #{display_revision(mirror, options["revision"])}" : ""
msg "Updating mirror '#{mirror.path}'#{revision_message}."
if mirror.type == "git-clone"
mirror.branch = options["branch"] || mirror.branch
# config.update(mirror)
mirror.rspec_git.update mirror.branch
config.update(mirror)
add_config_file
commit_message = "Updated clone repository '#{mirror.path}' to #{mirror.branch}"
else
# check options for lock modification
if mirror.locked?
if options["head"]
msg "Unlocking mirror '#{mirror.path}'." if verbose?
mirror.lock = nil
elsif !options["revision"]
msg "Mirror '#{mirror.path}' is locked to #{display_revision(mirror, mirror.lock)}. Use --head to force."
return
end
end
setup_remote(mirror)
msg "Fetching new commits for '#{mirror.path}'." if verbose?
mirror.fetch
new_revision = validate_new_revision(mirror, options["revision"])
target_revision = determine_target_revision(mirror, new_revision)
if mirror.merged?(target_revision)
msg "Mirror '#{mirror.path}' is already up to date."
return
end
if mirror.squashed?
diff = mirror.diff
base_revision = mirror.base_revision
end
mirror.revision = new_revision
mirror.lock = new_revision if options["revision"]
msg "Merging in mirror '#{mirror.path}'." if verbose?
begin
if mirror.squashed?
local_hash = git.rev_parse("HEAD")
if diff
base_hash = generate_tree_hash(mirror, base_revision)
else
base_hash = local_hash
end
remote_hash = generate_tree_hash(mirror, target_revision)
ENV["GITHEAD_#{local_hash}"] = "HEAD"
ENV["GITHEAD_#{remote_hash}"] = target_revision
git.merge_recursive(base_hash, local_hash, remote_hash)
else
git.merge_subtree(target_revision)
end
rescue Operations::MergeError => error
msg "Caught merge error. Breaking."
end
config.update(mirror)
add_config_file
commit_message = "Updated mirror '#{mirror.path}' to #{display_revision(mirror)}"
if error
File.open(".git/MERGE_MSG", 'w') { |f| f.puts(commit_message) }
return
end
end
git.commit(commit_message)
msg commit_message
end
def generate_tree_hash(mirror, revision)
git.rm_r(mirror.path)
git.read_tree_prefix(revision, mirror.path)
success = git.commit("Temporary commit for mirror '#{mirror.path}'")
hash = git.rev_parse("HEAD")
git.reset_hard("HEAD^") if success
hash
end
end
end
end