braid 1.1.8 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/braid/command.rb +39 -15
- data/lib/braid/commands/add.rb +22 -12
- data/lib/braid/commands/diff.rb +27 -10
- data/lib/braid/commands/push.rb +33 -18
- data/lib/braid/commands/remove.rb +17 -4
- data/lib/braid/commands/setup.rb +12 -3
- data/lib/braid/commands/status.rb +17 -8
- data/lib/braid/commands/update.rb +47 -23
- data/lib/braid/commands/upgrade_config.rb +18 -4
- data/lib/braid/config.rb +28 -18
- data/lib/braid/main.rb +47 -33
- data/lib/braid/mirror.rb +70 -44
- data/lib/braid/operations.rb +235 -79
- data/lib/braid/operations_lite.rb +1 -1
- data/lib/braid/sorbet/fake_runtime.rb +22 -0
- data/lib/braid/version.rb +1 -1
- data/lib/braid.rb +2 -10
- metadata +46 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f38ff51ac35694b840f6dbc049ae5bf630fc3b6cf0e6e781431c5f9190f12df1
|
4
|
+
data.tar.gz: de2a9463583afbbb4d0a380ffbef2d68defb9b505f7aa27a684e5bc53c5e4579
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7cf1ec0a11f3f02788d41cb710e49263e3ea429d9e0db7ee856453a3616fc7d8350498e96401efed19f45afa90fe4ef61bdfa484568b5520c78cbd67988120d4
|
7
|
+
data.tar.gz: f7dd2378a8fcb3704db070f20a814c7c4f90956e34684ad22d68335ac3f0ed37ce268bd43ebcab92427ad017c74fa5ed4f5225bfda6cf7623c01643d2561ef23
|
data/lib/braid/command.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
module Braid
|
3
3
|
class Command
|
4
4
|
extend T::Sig
|
@@ -9,15 +9,13 @@ module Braid
|
|
9
9
|
extend Operations::VersionControl
|
10
10
|
include Operations::VersionControl
|
11
11
|
|
12
|
-
|
12
|
+
sig {void}
|
13
|
+
def run
|
13
14
|
verify_git_version!
|
14
15
|
check_working_dir!
|
15
|
-
|
16
|
-
klass = Commands.const_get(command.to_s)
|
17
|
-
klass.new.run(*args)
|
18
|
-
|
16
|
+
run_internal
|
19
17
|
rescue BraidError => error
|
20
|
-
handle_error(error)
|
18
|
+
Command.handle_error(error)
|
21
19
|
end
|
22
20
|
|
23
21
|
sig {params(error: BraidError).returns(T.noreturn)}
|
@@ -36,13 +34,19 @@ module Braid
|
|
36
34
|
puts "Braid: #{str}"
|
37
35
|
end
|
38
36
|
|
37
|
+
sig {void}
|
38
|
+
def initialize
|
39
|
+
@config = T.let(nil, T.nilable(Config))
|
40
|
+
end
|
41
|
+
|
39
42
|
sig {params(str: String).void}
|
40
43
|
def msg(str)
|
41
44
|
self.class.msg(str)
|
42
45
|
end
|
43
46
|
|
47
|
+
sig {returns(Config)}
|
44
48
|
def config
|
45
|
-
@config ||= Config.new(
|
49
|
+
@config ||= Config.new(mode: config_mode)
|
46
50
|
end
|
47
51
|
|
48
52
|
sig {returns(T::Boolean)}
|
@@ -57,23 +61,32 @@ module Braid
|
|
57
61
|
|
58
62
|
private
|
59
63
|
|
64
|
+
# TODO (typing): We could make this method abstract if our fake Sorbet
|
65
|
+
# runtime supported abstract methods.
|
66
|
+
sig {void}
|
67
|
+
def run_internal
|
68
|
+
raise InternalError, 'Command.run_internal not overridden'
|
69
|
+
end
|
70
|
+
|
60
71
|
sig {returns(Config::ConfigMode)}
|
61
72
|
def config_mode
|
62
73
|
Config::MODE_MAY_WRITE
|
63
74
|
end
|
64
75
|
|
76
|
+
sig {params(mirror: Mirror).void}
|
65
77
|
def setup_remote(mirror)
|
66
78
|
existing_force = Braid.force
|
67
79
|
begin
|
68
80
|
Braid.force = true
|
69
|
-
|
81
|
+
Commands::Setup.new(mirror.path).run
|
70
82
|
ensure
|
71
83
|
Braid.force = existing_force
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
75
|
-
|
76
|
-
|
87
|
+
sig {params(mirror: Mirror).void}
|
88
|
+
def clear_remote(mirror)
|
89
|
+
git.remote_rm(mirror.remote)
|
77
90
|
end
|
78
91
|
|
79
92
|
sig {returns(T::Boolean)}
|
@@ -82,12 +95,12 @@ module Braid
|
|
82
95
|
end
|
83
96
|
|
84
97
|
sig {void}
|
85
|
-
def
|
98
|
+
def verify_git_version!
|
86
99
|
git.require_version!(REQUIRED_GIT_VERSION)
|
87
100
|
end
|
88
101
|
|
89
102
|
sig {void}
|
90
|
-
def
|
103
|
+
def check_working_dir!
|
91
104
|
# If we aren't in a git repository at all, git.is_inside_worktree will
|
92
105
|
# propagate a "fatal: Not a git repository" ShellException.
|
93
106
|
unless git.is_inside_worktree
|
@@ -103,7 +116,12 @@ module Braid
|
|
103
116
|
git.ensure_clean!
|
104
117
|
end
|
105
118
|
|
106
|
-
|
119
|
+
sig {
|
120
|
+
type_parameters(:R).params(
|
121
|
+
blk: T.proc.returns(T.type_parameter(:R))
|
122
|
+
).returns(T.type_parameter(:R))
|
123
|
+
}
|
124
|
+
def with_reset_on_error(&blk)
|
107
125
|
bail_on_local_changes!
|
108
126
|
|
109
127
|
work_head = git.head
|
@@ -123,11 +141,16 @@ module Braid
|
|
123
141
|
git.add(CONFIG_FILE)
|
124
142
|
end
|
125
143
|
|
144
|
+
sig {params(mirror: Mirror, revision: T.nilable(String)).returns(String)}
|
126
145
|
def display_revision(mirror, revision = nil)
|
127
|
-
|
146
|
+
# This shouldn't be called while `mirror.revision` is nil in the middle of
|
147
|
+
# `braid add`. TODO (typing): Remove `T.must` if we restructure the code
|
148
|
+
# so `mirror.revision` is annotated as non-nil.
|
149
|
+
revision ||= T.must(mirror.revision)
|
128
150
|
"'#{revision[0, 7]}'"
|
129
151
|
end
|
130
152
|
|
153
|
+
sig {params(mirror: Mirror).returns(Operations::Git::ObjectID)}
|
131
154
|
def determine_repository_revision(mirror)
|
132
155
|
if mirror.tag
|
133
156
|
if use_local_cache?
|
@@ -147,6 +170,7 @@ module Braid
|
|
147
170
|
end
|
148
171
|
end
|
149
172
|
|
173
|
+
sig {params(mirror: Mirror, revision: T.nilable(Operations::Git::ObjectExpr)).returns(Operations::Git::ObjectID)}
|
150
174
|
def validate_new_revision(mirror, revision)
|
151
175
|
if revision.nil?
|
152
176
|
determine_repository_revision(mirror)
|
data/lib/braid/commands/add.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
module Braid
|
3
3
|
module Commands
|
4
4
|
class Add < Command
|
@@ -13,6 +13,7 @@ module Braid
|
|
13
13
|
# the mirror to the remote HEAD revision, but that's probably not what the
|
14
14
|
# user wants. It's much more likely that something is wrong and Braid
|
15
15
|
# should report an error.
|
16
|
+
sig {params(url: String).returns(T.nilable(String))}
|
16
17
|
def get_default_branch_name(url)
|
17
18
|
head_targets = []
|
18
19
|
# The `HEAD` parameter here doesn't appear to do an exact match (it
|
@@ -20,7 +21,7 @@ module Braid
|
|
20
21
|
# as `refs/remotes/origin/HEAD` in the unusual case where the repository
|
21
22
|
# contains its own remote-tracking branches), but it reduces the data we
|
22
23
|
# have to scan a bit.
|
23
|
-
git.ls_remote('--symref', url, 'HEAD').split("\n").each do |line|
|
24
|
+
git.ls_remote(['--symref', url, 'HEAD']).split("\n").each do |line|
|
24
25
|
m = /^ref: (.*)\tHEAD$/.match(line)
|
25
26
|
head_targets.push(m[1]) if m
|
26
27
|
end
|
@@ -30,28 +31,37 @@ module Braid
|
|
30
31
|
m[1]
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
+
sig {params(url: String, options: Mirror::Options).void}
|
35
|
+
def initialize(url, options)
|
36
|
+
@url = url
|
37
|
+
@options = options
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
sig {void}
|
43
|
+
def run_internal
|
34
44
|
with_reset_on_error do
|
35
|
-
if options
|
36
|
-
default_branch = get_default_branch_name(url)
|
45
|
+
if @options.branch.nil? && @options.tag.nil? && @options.revision.nil?
|
46
|
+
default_branch = get_default_branch_name(@url)
|
37
47
|
if default_branch.nil?
|
38
48
|
raise BraidError, <<-MSG
|
39
49
|
Failed to detect the default branch of the remote repository. Please specify
|
40
50
|
the branch you want to use via the --branch option.
|
41
51
|
MSG
|
42
52
|
end
|
43
|
-
options
|
53
|
+
@options.branch = default_branch
|
44
54
|
end
|
45
55
|
|
46
|
-
mirror = config.add_from_options(url, options)
|
56
|
+
mirror = config.add_from_options(@url, @options)
|
47
57
|
add_config_file
|
48
58
|
|
49
|
-
mirror.branch = nil if options
|
50
|
-
raise BraidError, 'Can not add mirror specifying both a revision and a tag' if options
|
59
|
+
mirror.branch = nil if @options.revision
|
60
|
+
raise BraidError, 'Can not add mirror specifying both a revision and a tag' if @options.revision && mirror.tag
|
51
61
|
|
52
62
|
branch_message = mirror.branch.nil? ? '' : " branch '#{mirror.branch}'"
|
53
63
|
tag_message = mirror.tag.nil? ? '' : " tag '#{mirror.tag}'"
|
54
|
-
revision_message = options
|
64
|
+
revision_message = @options.revision ? " at #{display_revision(mirror, @options.revision)}" : ''
|
55
65
|
msg "Adding mirror of '#{mirror.url}'#{branch_message}#{tag_message}#{revision_message}."
|
56
66
|
|
57
67
|
# these commands are explained in the subtree merge guide
|
@@ -61,7 +71,7 @@ MSG
|
|
61
71
|
setup_remote(mirror)
|
62
72
|
mirror.fetch
|
63
73
|
|
64
|
-
new_revision = validate_new_revision(mirror, options
|
74
|
+
new_revision = validate_new_revision(mirror, @options.revision)
|
65
75
|
target_item = mirror.upstream_item_for_revision(new_revision)
|
66
76
|
|
67
77
|
git.add_item_to_index(target_item, mirror.path, true)
|
@@ -73,7 +83,7 @@ MSG
|
|
73
83
|
git.commit("Add mirror '#{mirror.path}' at #{display_revision(mirror)}")
|
74
84
|
msg "Added mirror at #{display_revision(mirror)}."
|
75
85
|
|
76
|
-
clear_remote(mirror
|
86
|
+
clear_remote(mirror)
|
77
87
|
end
|
78
88
|
end
|
79
89
|
end
|
data/lib/braid/commands/diff.rb
CHANGED
@@ -1,14 +1,27 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
module Braid
|
3
3
|
module Commands
|
4
4
|
class Diff < Command
|
5
|
-
|
6
|
-
|
5
|
+
class Options < T::Struct
|
6
|
+
prop :git_diff_args, T::Array[String]
|
7
|
+
prop :keep, T::Boolean
|
8
|
+
end
|
9
|
+
|
10
|
+
sig {params(path: T.nilable(String), options: Options).void}
|
11
|
+
def initialize(path, options)
|
12
|
+
@path = path
|
13
|
+
@options = options
|
7
14
|
end
|
8
15
|
|
9
16
|
private
|
10
17
|
|
11
|
-
|
18
|
+
sig {void}
|
19
|
+
def run_internal
|
20
|
+
@path ? diff_one(@path) : diff_all
|
21
|
+
end
|
22
|
+
|
23
|
+
sig {void}
|
24
|
+
def diff_all
|
12
25
|
# We don't want "git diff" to invoke the pager once for each mirror.
|
13
26
|
# TODO: Invoke the default pager once for the entire output.
|
14
27
|
Operations::with_modified_environment({ 'GIT_PAGER' => ''}) do
|
@@ -16,31 +29,35 @@ module Braid
|
|
16
29
|
separator
|
17
30
|
msg "Diffing #{path}\n"
|
18
31
|
separator
|
19
|
-
show_diff(path
|
32
|
+
show_diff(path)
|
20
33
|
end
|
21
34
|
end
|
22
35
|
end
|
23
36
|
|
24
|
-
|
25
|
-
|
37
|
+
sig {params(path: String).void}
|
38
|
+
def diff_one(path)
|
39
|
+
show_diff(path)
|
26
40
|
end
|
27
41
|
|
42
|
+
sig {void}
|
28
43
|
def separator
|
29
44
|
puts "=======================================================\n"
|
30
45
|
end
|
31
46
|
|
32
|
-
|
47
|
+
sig {params(path: String).void}
|
48
|
+
def show_diff(path)
|
33
49
|
mirror = config.get!(path)
|
34
50
|
setup_remote(mirror)
|
35
51
|
mirror.fetch_base_revision_if_missing
|
36
52
|
|
37
53
|
# XXX: Warn if the user specifies file paths that are outside the
|
38
54
|
# mirror? Currently, they just won't match anything.
|
39
|
-
git.diff_to_stdout(
|
55
|
+
git.diff_to_stdout(mirror.diff_args(@options.git_diff_args))
|
40
56
|
|
41
|
-
clear_remote(mirror
|
57
|
+
clear_remote(mirror) unless @options.keep
|
42
58
|
end
|
43
59
|
|
60
|
+
sig {returns(Config::ConfigMode)}
|
44
61
|
def config_mode
|
45
62
|
Config::MODE_READ_ONLY
|
46
63
|
end
|
data/lib/braid/commands/push.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
require 'fileutils'
|
3
3
|
require 'tmpdir'
|
4
4
|
|
5
5
|
module Braid
|
6
6
|
class NoPushToTag < BraidError
|
7
|
+
sig {returns(String)}
|
7
8
|
def message
|
8
9
|
"mirror is based off a tag. Can not push to a tag: #{super}"
|
9
10
|
end
|
@@ -11,12 +12,26 @@ module Braid
|
|
11
12
|
|
12
13
|
module Commands
|
13
14
|
class Push < Command
|
14
|
-
|
15
|
-
|
15
|
+
class Options < T::Struct
|
16
|
+
prop :keep, T::Boolean
|
17
|
+
prop :branch, T.nilable(String)
|
18
|
+
end
|
19
|
+
|
20
|
+
sig {params(path: String, options: Options).void}
|
21
|
+
def initialize(path, options)
|
22
|
+
@path = path
|
23
|
+
@options = options
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
16
27
|
|
17
|
-
|
28
|
+
sig {void}
|
29
|
+
def run_internal
|
30
|
+
mirror = config.get!(@path)
|
18
31
|
|
19
|
-
|
32
|
+
branch = @options.branch || mirror.branch
|
33
|
+
|
34
|
+
raise NoPushToTag, @path unless branch
|
20
35
|
|
21
36
|
setup_remote(mirror)
|
22
37
|
mirror.fetch
|
@@ -24,14 +39,14 @@ module Braid
|
|
24
39
|
base_revision = determine_repository_revision(mirror)
|
25
40
|
unless mirror.merged?(base_revision)
|
26
41
|
msg 'Mirror is not up to date. Stopping.'
|
27
|
-
clear_remote(mirror
|
42
|
+
clear_remote(mirror) unless @options.keep
|
28
43
|
return
|
29
44
|
end
|
30
45
|
|
31
46
|
diff = mirror.diff
|
32
47
|
if diff.empty?
|
33
48
|
msg 'No local changes found. Stopping.'
|
34
|
-
clear_remote(mirror
|
49
|
+
clear_remote(mirror) unless @options.keep
|
35
50
|
return
|
36
51
|
end
|
37
52
|
local_mirror_item = git.get_tree_item('HEAD', mirror.path)
|
@@ -44,7 +59,8 @@ module Braid
|
|
44
59
|
end
|
45
60
|
clone_dir = Dir.tmpdir + "/braid_push.#{$$}"
|
46
61
|
Dir.mkdir(clone_dir)
|
47
|
-
|
62
|
+
# TODO (typing): Remove this `T.must` somehow?
|
63
|
+
remote_url = T.must(git.remote_url(mirror.remote))
|
48
64
|
if remote_url == mirror.cached_url
|
49
65
|
remote_url = mirror.url
|
50
66
|
elsif File.directory?(remote_url)
|
@@ -68,7 +84,7 @@ module Braid
|
|
68
84
|
File.open('.git/objects/info/alternates', 'wb') { |f|
|
69
85
|
f.puts(odb_paths)
|
70
86
|
}
|
71
|
-
git.fetch(remote_url, mirror.remote_ref)
|
87
|
+
git.fetch(remote_url, [mirror.remote_ref])
|
72
88
|
new_tree = git.make_tree_with_item(base_revision,
|
73
89
|
mirror.remote_path || '', local_mirror_item)
|
74
90
|
if git.require_version('2.27')
|
@@ -106,22 +122,21 @@ module Braid
|
|
106
122
|
# Update HEAD the same way git.checkout(base_revision) would, but
|
107
123
|
# don't populate the index or working tree (to save us the trouble of
|
108
124
|
# emptying them again before the git.read_tree).
|
109
|
-
git.update_ref('--no-deref', 'HEAD', base_revision)
|
110
|
-
git.
|
125
|
+
git.update_ref(['--no-deref', 'HEAD', base_revision])
|
126
|
+
git.read_tree_um(new_tree)
|
111
127
|
system('git commit -v')
|
112
128
|
msg "Pushing changes to remote branch #{branch}."
|
113
|
-
git.push(remote_url, "HEAD:refs/heads/#{branch}")
|
129
|
+
git.push([remote_url, "HEAD:refs/heads/#{branch}"])
|
114
130
|
end
|
115
131
|
FileUtils.rm_r(clone_dir)
|
116
132
|
|
117
|
-
clear_remote(mirror
|
133
|
+
clear_remote(mirror) unless @options.keep
|
118
134
|
end
|
119
|
-
end
|
120
135
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
136
|
+
sig {returns(Config::ConfigMode)}
|
137
|
+
def config_mode
|
138
|
+
Config::MODE_READ_ONLY # Surprisingly enough.
|
139
|
+
end
|
125
140
|
end
|
126
141
|
end
|
127
142
|
end
|
@@ -1,9 +1,22 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
module Braid
|
3
3
|
module Commands
|
4
4
|
class Remove < Command
|
5
|
-
|
6
|
-
|
5
|
+
class Options < T::Struct
|
6
|
+
prop :keep, T::Boolean
|
7
|
+
end
|
8
|
+
|
9
|
+
sig {params(path: String, options: Options).void}
|
10
|
+
def initialize(path, options)
|
11
|
+
@path = path
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
sig {void}
|
18
|
+
def run_internal
|
19
|
+
mirror = config.get!(@path)
|
7
20
|
|
8
21
|
with_reset_on_error do
|
9
22
|
msg "Removing mirror from '#{mirror.path}'."
|
@@ -13,7 +26,7 @@ module Braid
|
|
13
26
|
config.remove(mirror)
|
14
27
|
add_config_file
|
15
28
|
|
16
|
-
if options
|
29
|
+
if @options.keep
|
17
30
|
msg "Not removing remote '#{mirror.remote}'" if verbose?
|
18
31
|
elsif git.remote_url(mirror.remote)
|
19
32
|
msg "Removed remote '#{mirror.path}'" if verbose?
|
data/lib/braid/commands/setup.rb
CHANGED
@@ -1,13 +1,20 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
module Braid
|
3
3
|
module Commands
|
4
4
|
class Setup < Command
|
5
|
-
|
6
|
-
|
5
|
+
sig {params(path: T.nilable(String)).void}
|
6
|
+
def initialize(path = nil)
|
7
|
+
@path = path
|
7
8
|
end
|
8
9
|
|
9
10
|
private
|
10
11
|
|
12
|
+
sig {void}
|
13
|
+
def run_internal
|
14
|
+
@path ? setup_one(@path) : setup_all
|
15
|
+
end
|
16
|
+
|
17
|
+
sig {void}
|
11
18
|
def setup_all
|
12
19
|
msg 'Setting up all mirrors.'
|
13
20
|
config.mirrors.each do |path|
|
@@ -15,6 +22,7 @@ module Braid
|
|
15
22
|
end
|
16
23
|
end
|
17
24
|
|
25
|
+
sig {params(path: String).void}
|
18
26
|
def setup_one(path)
|
19
27
|
mirror = config.get!(path)
|
20
28
|
|
@@ -33,6 +41,7 @@ module Braid
|
|
33
41
|
git.remote_add(mirror.remote, url)
|
34
42
|
end
|
35
43
|
|
44
|
+
sig {returns(Config::ConfigMode)}
|
36
45
|
def config_mode
|
37
46
|
Config::MODE_READ_ONLY
|
38
47
|
end
|
@@ -1,23 +1,31 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
module Braid
|
3
3
|
module Commands
|
4
4
|
class Status < Command
|
5
|
-
|
6
|
-
|
5
|
+
sig {params(path: T.nilable(String)).void}
|
6
|
+
def initialize(path)
|
7
|
+
@path = path
|
7
8
|
end
|
8
9
|
|
9
10
|
private
|
10
11
|
|
11
|
-
|
12
|
+
sig {void}
|
13
|
+
def run_internal
|
14
|
+
@path ? status_one(@path) : status_all
|
15
|
+
end
|
16
|
+
|
17
|
+
sig {void}
|
18
|
+
def status_all
|
12
19
|
print "\n"
|
13
20
|
msg "Listing all mirrors.\n=======================================================\n"
|
14
21
|
config.mirrors.each do |path|
|
15
|
-
status_one(path
|
22
|
+
status_one(path)
|
16
23
|
end
|
17
24
|
print "\n"
|
18
25
|
end
|
19
26
|
|
20
|
-
|
27
|
+
sig {params(path: String).void}
|
28
|
+
def status_one(path)
|
21
29
|
mirror = config.get!(path)
|
22
30
|
setup_remote(mirror)
|
23
31
|
mirror.fetch
|
@@ -31,7 +39,7 @@ module Braid
|
|
31
39
|
print " [BRANCH=#{mirror.branch}]"
|
32
40
|
end
|
33
41
|
msg "Fetching new commits for '#{mirror.path}'." if verbose?
|
34
|
-
new_revision = validate_new_revision(mirror,
|
42
|
+
new_revision = validate_new_revision(mirror, nil)
|
35
43
|
print ' (Remote Modified)' if new_revision.to_s != mirror.base_revision.to_s
|
36
44
|
local_file_count = git.read_ls_files(mirror.path).split.size
|
37
45
|
if 0 == local_file_count
|
@@ -40,9 +48,10 @@ module Braid
|
|
40
48
|
print ' (Locally Modified)'
|
41
49
|
end
|
42
50
|
print "\n"
|
43
|
-
clear_remote(mirror
|
51
|
+
clear_remote(mirror)
|
44
52
|
end
|
45
53
|
|
54
|
+
sig {returns(Config::ConfigMode)}
|
46
55
|
def config_mode
|
47
56
|
Config::MODE_READ_ONLY
|
48
57
|
end
|
@@ -1,26 +1,47 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
module Braid
|
3
3
|
module Commands
|
4
4
|
class Update < Command
|
5
|
-
|
6
|
-
|
5
|
+
class Options < T::Struct
|
6
|
+
prop :branch, T.nilable(String)
|
7
|
+
prop :tag, T.nilable(String)
|
8
|
+
prop :revision, T.nilable(Operations::Git::ObjectExpr)
|
9
|
+
prop :head, T::Boolean
|
10
|
+
prop :keep, T::Boolean
|
7
11
|
end
|
8
12
|
|
9
|
-
|
13
|
+
sig {params(path: T.nilable(String), options: Options).void}
|
14
|
+
def initialize(path, options)
|
15
|
+
@path = path
|
16
|
+
@options = options
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
sig {void}
|
22
|
+
def run_internal
|
23
|
+
@path ? update_one(@path) : update_all
|
24
|
+
end
|
25
|
+
|
26
|
+
sig {void}
|
27
|
+
def update_all
|
28
|
+
# Maintain previous behavior of ignoring these options when updating all
|
29
|
+
# mirrors. TODO: Should we make it an error if the options were passed?
|
30
|
+
@options.revision = nil
|
31
|
+
@options.head = false
|
10
32
|
|
11
|
-
def update_all(options = {})
|
12
|
-
options.reject! { |k, v| %w(revision head).include?(k) }
|
13
33
|
msg 'Updating all mirrors.'
|
14
34
|
config.mirrors.each do |path|
|
15
35
|
bail_on_local_changes!
|
16
|
-
update_one(path
|
36
|
+
update_one(path)
|
17
37
|
end
|
18
38
|
end
|
19
39
|
|
20
|
-
|
40
|
+
sig {params(path: String).void}
|
41
|
+
def update_one(path)
|
21
42
|
bail_on_local_changes!
|
22
43
|
|
23
|
-
raise BraidError, "Do not specify --head option anymore. Please use '--branch MyBranch' to track a branch or '--tag MyTag' to track a branch" if options
|
44
|
+
raise BraidError, "Do not specify --head option anymore. Please use '--branch MyBranch' to track a branch or '--tag MyTag' to track a branch" if @options.head
|
24
45
|
|
25
46
|
mirror = config.get!(path)
|
26
47
|
|
@@ -31,16 +52,16 @@ module Braid
|
|
31
52
|
original_branch = mirror.branch
|
32
53
|
original_tag = mirror.tag
|
33
54
|
|
34
|
-
raise BraidError, 'Can not update mirror specifying both a revision and a tag' if options
|
35
|
-
raise BraidError, 'Can not update mirror specifying both a branch and a tag' if options
|
55
|
+
raise BraidError, 'Can not update mirror specifying both a revision and a tag' if @options.revision && @options.tag
|
56
|
+
raise BraidError, 'Can not update mirror specifying both a branch and a tag' if @options.branch && @options.tag
|
36
57
|
|
37
|
-
if options
|
38
|
-
mirror.tag = options
|
58
|
+
if @options.tag
|
59
|
+
mirror.tag = @options.tag
|
39
60
|
mirror.branch = nil
|
40
|
-
elsif options
|
61
|
+
elsif @options.branch
|
41
62
|
mirror.tag = nil
|
42
|
-
mirror.branch = options
|
43
|
-
elsif options
|
63
|
+
mirror.branch = @options.branch
|
64
|
+
elsif @options.revision
|
44
65
|
mirror.tag = nil
|
45
66
|
mirror.branch = nil
|
46
67
|
end
|
@@ -51,11 +72,14 @@ module Braid
|
|
51
72
|
msg "Fetching new commits for '#{mirror.path}'." if verbose?
|
52
73
|
mirror.fetch
|
53
74
|
|
54
|
-
new_revision = options
|
75
|
+
new_revision = @options.revision
|
55
76
|
begin
|
56
77
|
new_revision = validate_new_revision(mirror, new_revision)
|
57
78
|
rescue InvalidRevision
|
58
79
|
# Ignored as it means the revision matches expected
|
80
|
+
# This can only happen if new_revision was non-nil.
|
81
|
+
# TODO (typing): Untangle the logic and remote this `T.must`.
|
82
|
+
new_revision = T.must(new_revision)
|
59
83
|
end
|
60
84
|
|
61
85
|
from_desc =
|
@@ -68,19 +92,19 @@ module Braid
|
|
68
92
|
msg "Switching mirror '#{mirror.path}' to branch '#{mirror.branch}' from #{from_desc}."
|
69
93
|
elsif mirror.tag && original_tag != mirror.tag
|
70
94
|
msg "Switching mirror '#{mirror.path}' to tag '#{mirror.tag}' from #{from_desc}."
|
71
|
-
elsif options
|
72
|
-
msg "Switching mirror '#{mirror.path}' to revision '#{options
|
95
|
+
elsif @options.revision && original_revision != @options.revision
|
96
|
+
msg "Switching mirror '#{mirror.path}' to revision '#{@options.revision}' from #{from_desc}."
|
73
97
|
else
|
74
98
|
switching = false
|
75
99
|
end
|
76
100
|
|
77
101
|
if !switching &&
|
78
102
|
(
|
79
|
-
(options
|
80
|
-
(options
|
103
|
+
(@options.revision && was_locked && new_revision == mirror.base_revision) ||
|
104
|
+
(@options.revision.nil? && !was_locked && mirror.merged?(git.rev_parse(new_revision)))
|
81
105
|
)
|
82
106
|
msg "Mirror '#{mirror.path}' is already up to date."
|
83
|
-
clear_remote(mirror
|
107
|
+
clear_remote(mirror) unless @options.keep
|
84
108
|
return
|
85
109
|
end
|
86
110
|
|
@@ -120,7 +144,7 @@ module Braid
|
|
120
144
|
|
121
145
|
git.commit(commit_message)
|
122
146
|
msg "Updated mirror to #{display_revision(mirror)}."
|
123
|
-
clear_remote(mirror
|
147
|
+
clear_remote(mirror) unless @options.keep
|
124
148
|
end
|
125
149
|
end
|
126
150
|
end
|