braid 0.7.1 → 1.0.0
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 +7 -0
- data/.gitignore +4 -1
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CONTRIBUTING.md +26 -0
- data/Gemfile +1 -2
- data/LICENSE +3 -1
- data/README.md +90 -51
- data/Rakefile +6 -14
- data/bin/braid +9 -37
- data/braid.gemspec +11 -11
- data/lib/braid.rb +13 -12
- data/lib/braid/command.rb +9 -42
- data/lib/braid/commands/add.rb +6 -8
- data/lib/braid/commands/list.rb +11 -6
- data/lib/braid/commands/push.rb +5 -5
- data/lib/braid/commands/remove.rb +1 -3
- data/lib/braid/commands/setup.rb +4 -8
- data/lib/braid/commands/update.rb +12 -14
- data/lib/braid/config.rb +38 -43
- data/lib/braid/mirror.rb +19 -63
- data/lib/braid/operations.rb +51 -90
- data/lib/braid/version.rb +1 -1
- data/{test/config_test.rb → spec/config_spec.rb} +14 -17
- data/{test → spec}/fixtures/shiny/README +0 -0
- data/{test → spec}/fixtures/skit1.1/layouts/layout.liquid +0 -0
- data/{test → spec}/fixtures/skit1.2/layouts/layout.liquid +0 -0
- data/{test → spec}/fixtures/skit1/layouts/layout.liquid +0 -0
- data/{test → spec}/fixtures/skit1/preview.png +0 -0
- data/spec/integration/adding_spec.rb +43 -0
- data/{test/integration/updating_test.rb → spec/integration/updating_spec.rb} +2 -41
- data/spec/integration_helper.rb +47 -0
- data/{test/mirror_test.rb → spec/mirror_spec.rb} +6 -33
- data/{test/operations_test.rb → spec/operations_spec.rb} +2 -2
- data/{test → spec}/test_helper.rb +6 -2
- metadata +86 -123
- data/lib/core_ext.rb +0 -13
- data/test/braid_test.rb +0 -7
- data/test/integration/adding_test.rb +0 -80
- data/test/integration_helper.rb +0 -70
data/lib/braid.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
$:.unshift dirname = File.dirname(__FILE__)
|
2
1
|
require 'braid/version'
|
3
2
|
|
4
3
|
module Braid
|
5
|
-
CONFIG_FILE =
|
6
|
-
REQUIRED_GIT_VERSION =
|
4
|
+
CONFIG_FILE = '.braids'
|
5
|
+
REQUIRED_GIT_VERSION = '1.6'
|
7
6
|
|
8
7
|
def self.verbose
|
9
|
-
|
8
|
+
!!@verbose
|
10
9
|
end
|
11
10
|
|
12
11
|
def self.verbose=(new_value)
|
@@ -14,7 +13,7 @@ module Braid
|
|
14
13
|
end
|
15
14
|
|
16
15
|
def self.force
|
17
|
-
|
16
|
+
!!@force
|
18
17
|
end
|
19
18
|
|
20
19
|
def self.force=(new_value)
|
@@ -22,11 +21,11 @@ module Braid
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def self.use_local_cache
|
25
|
-
[nil,
|
24
|
+
[nil, 'true', '1'].include?(ENV['BRAID_USE_LOCAL_CACHE'])
|
26
25
|
end
|
27
26
|
|
28
27
|
def self.local_cache_dir
|
29
|
-
File.expand_path(ENV[
|
28
|
+
File.expand_path(ENV['BRAID_LOCAL_CACHE_DIR'] || "#{ENV['HOME']}/.braid/cache")
|
30
29
|
end
|
31
30
|
|
32
31
|
class BraidError < StandardError
|
@@ -37,12 +36,14 @@ module Braid
|
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
|
-
require dirname + '/core_ext'
|
41
39
|
require 'braid/operations'
|
42
40
|
require 'braid/mirror'
|
43
41
|
require 'braid/config'
|
44
42
|
require 'braid/command'
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
require 'braid/commands/add'
|
44
|
+
require 'braid/commands/diff'
|
45
|
+
require 'braid/commands/list'
|
46
|
+
require 'braid/commands/push'
|
47
|
+
require 'braid/commands/remove'
|
48
|
+
require 'braid/commands/setup'
|
49
|
+
require 'braid/commands/update'
|
data/lib/braid/command.rb
CHANGED
@@ -31,7 +31,7 @@ module Braid
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def config
|
34
|
-
@config ||=
|
34
|
+
@config ||= Config.new
|
35
35
|
end
|
36
36
|
|
37
37
|
def verbose?
|
@@ -61,6 +61,8 @@ module Braid
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def with_reset_on_error
|
64
|
+
bail_on_local_changes!
|
65
|
+
|
64
66
|
work_head = git.head
|
65
67
|
|
66
68
|
begin
|
@@ -72,65 +74,30 @@ module Braid
|
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
75
|
-
def load_and_migrate_config
|
76
|
-
config = Config.new
|
77
|
-
unless config.valid?
|
78
|
-
msg "Configuration is outdated. Migrating."
|
79
|
-
bail_on_local_changes!
|
80
|
-
config.migrate!
|
81
|
-
git.commit("Upgrade .braids", "-- .braids")
|
82
|
-
end
|
83
|
-
config
|
84
|
-
end
|
85
|
-
|
86
77
|
def add_config_file
|
87
78
|
git.add(CONFIG_FILE)
|
88
79
|
end
|
89
80
|
|
90
81
|
def display_revision(mirror, revision = nil)
|
91
82
|
revision ||= mirror.revision
|
92
|
-
|
83
|
+
"'#{revision[0, 7]}'"
|
93
84
|
end
|
94
85
|
|
95
86
|
def validate_new_revision(mirror, new_revision)
|
96
|
-
unless new_revision
|
97
|
-
unless mirror.type == "svn"
|
98
|
-
return git.rev_parse(mirror.remote)
|
99
|
-
else
|
100
|
-
return svn.head_revision(mirror.url)
|
101
|
-
end
|
102
|
-
end
|
87
|
+
return git.rev_parse(mirror.remote) unless new_revision
|
103
88
|
|
104
|
-
|
105
|
-
new_revision = git.rev_parse(new_revision)
|
106
|
-
else
|
107
|
-
new_revision = svn.clean_revision(new_revision)
|
108
|
-
end
|
89
|
+
new_revision = git.rev_parse(new_revision)
|
109
90
|
old_revision = mirror.revision
|
110
91
|
|
111
92
|
if new_revision == old_revision
|
112
|
-
raise InvalidRevision,
|
113
|
-
end
|
114
|
-
|
115
|
-
if mirror.type == "svn"
|
116
|
-
if old_revision && new_revision < old_revision
|
117
|
-
raise InvalidRevision, "local revision is higher than request revision"
|
118
|
-
end
|
119
|
-
|
120
|
-
if svn.head_revision(mirror.url) < new_revision
|
121
|
-
raise InvalidRevision, "requested revision is higher than remote revision"
|
122
|
-
end
|
93
|
+
raise InvalidRevision, 'mirror is already at requested revision'
|
123
94
|
end
|
124
95
|
|
125
96
|
new_revision
|
126
97
|
end
|
127
98
|
|
128
|
-
def determine_target_revision(
|
129
|
-
|
130
|
-
git.rev_parse(new_revision)
|
131
|
-
else
|
132
|
-
git_svn.commit_hash(mirror.remote, new_revision)
|
133
|
-
end
|
99
|
+
def determine_target_revision(new_revision)
|
100
|
+
git.rev_parse(new_revision)
|
134
101
|
end
|
135
102
|
end
|
136
103
|
end
|
data/lib/braid/commands/add.rb
CHANGED
@@ -2,14 +2,12 @@ module Braid
|
|
2
2
|
module Commands
|
3
3
|
class Add < Command
|
4
4
|
def run(url, options = {})
|
5
|
-
bail_on_local_changes!
|
6
|
-
|
7
5
|
with_reset_on_error do
|
8
6
|
mirror = config.add_from_options(url, options)
|
9
7
|
|
10
|
-
branch_message = (mirror.
|
11
|
-
revision_message = options[
|
12
|
-
msg "Adding
|
8
|
+
branch_message = (mirror.branch == 'master') ? '' : " branch '#{mirror.branch}'"
|
9
|
+
revision_message = options['revision'] ? " at #{display_revision(mirror, options['revision'])}" : ''
|
10
|
+
msg "Adding mirror of '#{mirror.url}'#{branch_message}#{revision_message}."
|
13
11
|
|
14
12
|
# these commands are explained in the subtree merge guide
|
15
13
|
# http://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html
|
@@ -17,8 +15,8 @@ module Braid
|
|
17
15
|
setup_remote(mirror)
|
18
16
|
mirror.fetch
|
19
17
|
|
20
|
-
new_revision = validate_new_revision(mirror, options[
|
21
|
-
target_revision = determine_target_revision(
|
18
|
+
new_revision = validate_new_revision(mirror, options['revision'])
|
19
|
+
target_revision = determine_target_revision(new_revision)
|
22
20
|
|
23
21
|
unless mirror.squashed?
|
24
22
|
git.merge_ours(target_revision)
|
@@ -26,7 +24,7 @@ module Braid
|
|
26
24
|
git.read_tree_prefix(target_revision, mirror.path)
|
27
25
|
|
28
26
|
mirror.revision = new_revision
|
29
|
-
mirror.lock = new_revision if options[
|
27
|
+
mirror.lock = new_revision if options['revision']
|
30
28
|
config.update(mirror)
|
31
29
|
add_config_file
|
32
30
|
|
data/lib/braid/commands/list.rb
CHANGED
@@ -12,16 +12,21 @@ module Braid
|
|
12
12
|
options.reject! { |k, v| %w(revision head).include?(k) }
|
13
13
|
print "\n"
|
14
14
|
msg "Listing all mirrors.\n=======================================================\n"
|
15
|
-
config.mirrors.
|
15
|
+
config.mirrors.each do |path|
|
16
16
|
mirror = config.get!(path)
|
17
|
-
print
|
18
|
-
print
|
17
|
+
print path.to_s
|
18
|
+
print ' [LOCKED]' if mirror.locked?
|
19
19
|
setup_remote(mirror)
|
20
20
|
msg "Fetching new commits for '#{mirror.path}'." if verbose?
|
21
21
|
mirror.fetch
|
22
|
-
new_revision = validate_new_revision(mirror, options[
|
23
|
-
|
24
|
-
|
22
|
+
new_revision = validate_new_revision(mirror, options['revision'])
|
23
|
+
print ' (Remote Modified)' if new_revision.to_s != mirror.base_revision.to_s
|
24
|
+
local_file_count = git.read_ls_files(mirror.path).split.size
|
25
|
+
if 0 == local_file_count
|
26
|
+
print ' (Removed Locally)'
|
27
|
+
elsif !mirror.diff.empty?
|
28
|
+
print ' (Locally Modified)'
|
29
|
+
end
|
25
30
|
print "\n"
|
26
31
|
end
|
27
32
|
print "\n"
|
data/lib/braid/commands/push.rb
CHANGED
@@ -11,13 +11,13 @@ module Braid
|
|
11
11
|
|
12
12
|
base_revision = git.rev_parse(mirror.remote)
|
13
13
|
unless mirror.merged?(base_revision)
|
14
|
-
msg
|
14
|
+
msg 'Mirror is not up to date. Stopping.'
|
15
15
|
return
|
16
16
|
end
|
17
17
|
|
18
18
|
diff = mirror.diff
|
19
19
|
if diff.empty?
|
20
|
-
msg
|
20
|
+
msg 'No local changes found. Stopping.'
|
21
21
|
return
|
22
22
|
end
|
23
23
|
|
@@ -31,14 +31,14 @@ module Braid
|
|
31
31
|
remote_url = File.expand_path(remote_url)
|
32
32
|
end
|
33
33
|
Dir.chdir(clone_dir) do
|
34
|
-
msg
|
34
|
+
msg 'Cloning mirror with local changes.'
|
35
35
|
git.init
|
36
36
|
git.fetch(source_dir)
|
37
37
|
git.fetch(remote_url, "+refs/heads/#{mirror.branch}")
|
38
38
|
git.checkout(base_revision)
|
39
39
|
git.apply(diff)
|
40
|
-
system(
|
41
|
-
msg
|
40
|
+
system('git commit -v')
|
41
|
+
msg 'Pushing changes to remote.'
|
42
42
|
git.push(remote_url, "HEAD:#{mirror.branch}")
|
43
43
|
end
|
44
44
|
FileUtils.rm_r(clone_dir)
|
@@ -4,8 +4,6 @@ module Braid
|
|
4
4
|
def run(path, options = {})
|
5
5
|
mirror = config.get!(path)
|
6
6
|
|
7
|
-
bail_on_local_changes!
|
8
|
-
|
9
7
|
with_reset_on_error do
|
10
8
|
msg "Removing mirror from '#{mirror.path}'."
|
11
9
|
|
@@ -24,7 +22,7 @@ module Braid
|
|
24
22
|
end
|
25
23
|
|
26
24
|
git.commit("Remove mirror '#{mirror.path}'")
|
27
|
-
msg
|
25
|
+
msg 'Removed mirror.' if verbose?
|
28
26
|
end
|
29
27
|
end
|
30
28
|
end
|
data/lib/braid/commands/setup.rb
CHANGED
@@ -6,9 +6,9 @@ module Braid
|
|
6
6
|
end
|
7
7
|
|
8
8
|
protected
|
9
|
-
|
9
|
+
|
10
10
|
def setup_all
|
11
|
-
msg
|
11
|
+
msg 'Setting up all mirrors.'
|
12
12
|
config.mirrors.each do |path|
|
13
13
|
setup_one(path)
|
14
14
|
end
|
@@ -28,12 +28,8 @@ module Braid
|
|
28
28
|
end
|
29
29
|
|
30
30
|
msg "Setup: Creating remote for '#{mirror.path}'."
|
31
|
-
|
32
|
-
|
33
|
-
git.remote_add(mirror.remote, url, mirror.branch)
|
34
|
-
else
|
35
|
-
git_svn.init(mirror.remote, mirror.url)
|
36
|
-
end
|
31
|
+
url = use_local_cache? ? git_cache.path(mirror.url) : mirror.url
|
32
|
+
git.remote_add(mirror.remote, url, mirror.branch)
|
37
33
|
end
|
38
34
|
end
|
39
35
|
end
|
@@ -2,8 +2,6 @@ module Braid
|
|
2
2
|
module Commands
|
3
3
|
class Update < Command
|
4
4
|
def run(path, options = {})
|
5
|
-
bail_on_local_changes!
|
6
|
-
|
7
5
|
with_reset_on_error do
|
8
6
|
path ? update_one(path, options) : update_all(options)
|
9
7
|
end
|
@@ -13,7 +11,7 @@ module Braid
|
|
13
11
|
|
14
12
|
def update_all(options = {})
|
15
13
|
options.reject! { |k, v| %w(revision head).include?(k) }
|
16
|
-
msg
|
14
|
+
msg 'Updating all mirrors.'
|
17
15
|
config.mirrors.each do |path|
|
18
16
|
update_one(path, options)
|
19
17
|
end
|
@@ -27,10 +25,10 @@ module Braid
|
|
27
25
|
|
28
26
|
# check options for lock modification
|
29
27
|
if mirror.locked?
|
30
|
-
if options[
|
28
|
+
if options['head']
|
31
29
|
msg "Unlocking mirror '#{mirror.path}'." if verbose?
|
32
30
|
mirror.lock = nil
|
33
|
-
elsif !options[
|
31
|
+
elsif !options['revision']
|
34
32
|
msg "Mirror '#{mirror.path}' is locked to #{display_revision(mirror, mirror.lock)}. Use --head to force."
|
35
33
|
return
|
36
34
|
end
|
@@ -40,8 +38,8 @@ module Braid
|
|
40
38
|
msg "Fetching new commits for '#{mirror.path}'." if verbose?
|
41
39
|
mirror.fetch
|
42
40
|
|
43
|
-
new_revision = validate_new_revision(mirror, options[
|
44
|
-
target_revision = determine_target_revision(
|
41
|
+
new_revision = validate_new_revision(mirror, options['revision'])
|
42
|
+
target_revision = determine_target_revision(new_revision)
|
45
43
|
|
46
44
|
if mirror.merged?(target_revision)
|
47
45
|
msg "Mirror '#{mirror.path}' is already up to date."
|
@@ -54,26 +52,26 @@ module Braid
|
|
54
52
|
end
|
55
53
|
|
56
54
|
mirror.revision = new_revision
|
57
|
-
mirror.lock = new_revision if options[
|
55
|
+
mirror.lock = new_revision if options['revision']
|
58
56
|
|
59
57
|
msg "Merging in mirror '#{mirror.path}'." if verbose?
|
60
58
|
begin
|
61
59
|
if mirror.squashed?
|
62
|
-
local_hash = git.rev_parse(
|
60
|
+
local_hash = git.rev_parse('HEAD')
|
63
61
|
if !diff.empty?
|
64
62
|
base_hash = generate_tree_hash(mirror, base_revision)
|
65
63
|
else
|
66
64
|
base_hash = local_hash
|
67
65
|
end
|
68
66
|
remote_hash = generate_tree_hash(mirror, target_revision)
|
69
|
-
ENV["GITHEAD_#{local_hash}"] =
|
67
|
+
ENV["GITHEAD_#{local_hash}"] = 'HEAD'
|
70
68
|
ENV["GITHEAD_#{remote_hash}"] = target_revision
|
71
69
|
git.merge_recursive(base_hash, local_hash, remote_hash)
|
72
70
|
else
|
73
71
|
git.merge_subtree(target_revision)
|
74
72
|
end
|
75
73
|
rescue Operations::MergeError => error
|
76
|
-
msg
|
74
|
+
msg 'Caught merge error. Breaking.'
|
77
75
|
end
|
78
76
|
|
79
77
|
config.update(mirror)
|
@@ -81,7 +79,7 @@ module Braid
|
|
81
79
|
|
82
80
|
commit_message = "Update mirror '#{mirror.path}' to #{display_revision(mirror)}"
|
83
81
|
if error
|
84
|
-
File.open(
|
82
|
+
File.open('.git/MERGE_MSG', 'w') { |f| f.puts(commit_message) }
|
85
83
|
return
|
86
84
|
end
|
87
85
|
|
@@ -93,8 +91,8 @@ module Braid
|
|
93
91
|
git.rm_r(mirror.path)
|
94
92
|
git.read_tree_prefix(revision, mirror.path)
|
95
93
|
success = git.commit("Temporary commit for mirror '#{mirror.path}'")
|
96
|
-
hash = git.rev_parse(
|
97
|
-
git.reset_hard(
|
94
|
+
hash = git.rev_parse('HEAD')
|
95
|
+
git.reset_hard('HEAD^') if success
|
98
96
|
hash
|
99
97
|
end
|
100
98
|
end
|
data/lib/braid/config.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
require 'json'
|
2
3
|
require 'yaml/store'
|
3
4
|
|
4
5
|
module Braid
|
@@ -15,7 +16,18 @@ module Braid
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def initialize(config_file = CONFIG_FILE)
|
18
|
-
@
|
19
|
+
@config_file = config_file
|
20
|
+
begin
|
21
|
+
store = YAML::Store.new(@config_file)
|
22
|
+
@db = {}
|
23
|
+
store.transaction(true) do
|
24
|
+
store.roots.each do |path|
|
25
|
+
@db[path] = store[path]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
rescue
|
29
|
+
@db = JSON.parse(@config_file)
|
30
|
+
end
|
19
31
|
end
|
20
32
|
|
21
33
|
def add_from_options(url, options)
|
@@ -26,17 +38,13 @@ module Braid
|
|
26
38
|
end
|
27
39
|
|
28
40
|
def mirrors
|
29
|
-
@db.
|
30
|
-
@db.roots
|
31
|
-
end
|
41
|
+
@db.keys
|
32
42
|
end
|
33
43
|
|
34
44
|
def get(path)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
45
|
+
key = path.to_s.sub(/\/$/, '')
|
46
|
+
attributes = @db[key]
|
47
|
+
return attributes ? Mirror.new(path, attributes) : nil
|
40
48
|
end
|
41
49
|
|
42
50
|
def get!(path)
|
@@ -46,52 +54,39 @@ module Braid
|
|
46
54
|
end
|
47
55
|
|
48
56
|
def add(mirror)
|
49
|
-
|
50
|
-
|
51
|
-
write_mirror(mirror)
|
52
|
-
end
|
57
|
+
raise PathAlreadyInUse, mirror.path if get(mirror.path)
|
58
|
+
write_mirror(mirror)
|
53
59
|
end
|
54
60
|
|
55
61
|
def remove(mirror)
|
56
|
-
@db.
|
57
|
-
|
58
|
-
end
|
62
|
+
@db.delete(mirror.path)
|
63
|
+
write_db
|
59
64
|
end
|
60
65
|
|
61
66
|
def update(mirror)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
write_mirror(mirror)
|
66
|
-
end
|
67
|
+
raise MirrorDoesNotExist, mirror.path unless get(mirror.path)
|
68
|
+
@db.delete(mirror.path)
|
69
|
+
write_mirror(mirror)
|
67
70
|
end
|
68
71
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
72
|
+
private
|
73
|
+
def write_mirror(mirror)
|
74
|
+
@db[mirror.path] = clean_attributes(mirror.attributes)
|
75
|
+
write_db
|
75
76
|
end
|
76
77
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
attributes["remote"] = attributes.delete("local_branch")
|
84
|
-
attributes["squashed"] = attributes.delete("squash")
|
85
|
-
attributes["lock"] = attributes["revision"] # so far this has always been true
|
86
|
-
end
|
87
|
-
@db[path] = clean_attributes(attributes)
|
78
|
+
def write_db
|
79
|
+
new_db = {}
|
80
|
+
@db.keys.sort.each do |key|
|
81
|
+
new_db[key] = @db[key]
|
82
|
+
new_db[key].keys.each do |k|
|
83
|
+
new_db[key].delete(k) if !Braid::Mirror::ATTRIBUTES.include?(k)
|
88
84
|
end
|
89
85
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
@db[mirror.path] = clean_attributes(mirror.attributes)
|
86
|
+
File.open(@config_file, "wb") do |f|
|
87
|
+
f.write JSON.pretty_generate(new_db)
|
88
|
+
f.write "\n"
|
89
|
+
end
|
95
90
|
end
|
96
91
|
|
97
92
|
def clean_attributes(hash)
|