git-multirepo 1.0.0.beta34 → 1.0.0.beta37

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -2
  3. data/.gitignore +38 -38
  4. data/.multirepo.meta +2 -2
  5. data/.rspec +2 -2
  6. data/Gemfile +4 -4
  7. data/Gemfile.lock +38 -38
  8. data/LICENSE +22 -22
  9. data/README.md +143 -143
  10. data/Rakefile +2 -2
  11. data/bin/multi +10 -10
  12. data/docs/bug-repros/91565510-repro.sh +20 -20
  13. data/docs/git-multirepo-node-dependency-depth-algorithm.pdf +0 -0
  14. data/docs/graphs/dependencies-on-multiple-levels.graffle +0 -0
  15. data/docs/graphs/dependencies-on-one-level.graffle +0 -0
  16. data/git-multirepo.gemspec +29 -29
  17. data/lib/commands.rb +13 -12
  18. data/lib/git-multirepo.rb +1 -1
  19. data/lib/info.rb +4 -4
  20. data/lib/multirepo/commands/add-command.rb +53 -51
  21. data/lib/multirepo/commands/branch-command.rb +65 -60
  22. data/lib/multirepo/commands/checkout-command.rb +119 -140
  23. data/lib/multirepo/commands/clean-command.rb +31 -31
  24. data/lib/multirepo/commands/clone-command.rb +70 -70
  25. data/lib/multirepo/commands/command.rb +71 -71
  26. data/lib/multirepo/commands/fetch-command.rb +30 -30
  27. data/lib/multirepo/commands/init-command.rb +119 -119
  28. data/lib/multirepo/commands/install-command.rb +103 -103
  29. data/lib/multirepo/commands/merge-command.rb +126 -0
  30. data/lib/multirepo/commands/open-command.rb +26 -26
  31. data/lib/multirepo/commands/remove-command.rb +50 -49
  32. data/lib/multirepo/commands/uninit-command.rb +20 -20
  33. data/lib/multirepo/commands/update-command.rb +59 -59
  34. data/lib/multirepo/config.rb +15 -15
  35. data/lib/multirepo/files/config-entry.rb +34 -34
  36. data/lib/multirepo/files/config-file.rb +45 -34
  37. data/lib/multirepo/files/lock-entry.rb +24 -25
  38. data/lib/multirepo/files/lock-file.rb +39 -28
  39. data/lib/multirepo/files/meta-file.rb +41 -33
  40. data/lib/multirepo/files/tracking-file.rb +8 -8
  41. data/lib/multirepo/files/tracking-files.rb +41 -43
  42. data/lib/multirepo/git/branch.rb +27 -27
  43. data/lib/multirepo/git/change.rb +10 -10
  44. data/lib/multirepo/git/commit.rb +17 -17
  45. data/lib/multirepo/git/git.rb +39 -39
  46. data/lib/multirepo/git/remote.rb +16 -16
  47. data/lib/multirepo/git/repo.rb +77 -77
  48. data/lib/multirepo/hooks/post-commit-hook.rb +22 -22
  49. data/lib/multirepo/hooks/pre-commit-hook.rb +29 -29
  50. data/lib/multirepo/logic/node.rb +41 -0
  51. data/lib/multirepo/logic/performer.rb +59 -0
  52. data/lib/multirepo/logic/revision-selector.rb +27 -0
  53. data/lib/multirepo/multirepo-exception.rb +5 -5
  54. data/lib/multirepo/utility/console.rb +51 -51
  55. data/lib/multirepo/utility/runner.rb +34 -34
  56. data/lib/multirepo/utility/utils.rb +65 -66
  57. data/resources/.gitconfig +2 -2
  58. data/resources/post-commit +5 -5
  59. data/resources/pre-commit +5 -5
  60. data/spec/integration/init_spec.rb +18 -18
  61. data/spec/spec_helper.rb +89 -89
  62. metadata +10 -3
@@ -1,34 +1,42 @@
1
- require "pathname"
2
- require "psych"
3
-
4
- require "info"
5
- require "multirepo/git/git"
6
- require_relative "tracking-file"
7
- require_relative "lock-entry"
8
- require_relative "config-file"
9
-
10
- module MultiRepo
11
- class MetaFile < TrackingFile
12
- FILE = Pathname.new(".multirepo.meta")
13
- FILENAME = FILE.to_s
14
-
15
- attr_accessor :version
16
-
17
- def initialize
18
- @version = MultiRepo::VERSION
19
- end
20
-
21
- def encode_with(coder)
22
- coder["version"] = @version
23
- end
24
-
25
- def self.load
26
- Psych.load(FILE.read)
27
- end
28
-
29
- def self.update
30
- content = Psych.dump(MetaFile.new)
31
- return update_internal(FILENAME, content)
32
- end
33
- end
1
+ require "pathname"
2
+ require "psych"
3
+
4
+ require "info"
5
+ require "multirepo/git/git"
6
+ require_relative "tracking-file"
7
+ require_relative "lock-entry"
8
+ require_relative "config-file"
9
+
10
+ module MultiRepo
11
+ class MetaFile < TrackingFile
12
+ FILENAME = ".multirepo.meta"
13
+
14
+ attr_accessor :version
15
+
16
+ def initialize(path)
17
+ @path = path
18
+ @version = MultiRepo::VERSION
19
+ end
20
+
21
+ def file
22
+ File.join(@path, FILENAME)
23
+ end
24
+
25
+ def filename
26
+ FILENAME
27
+ end
28
+
29
+ def encode_with(coder)
30
+ coder["version"] = @version
31
+ end
32
+
33
+ def load
34
+ Psych.load(file)
35
+ end
36
+
37
+ def update
38
+ content = Psych.dump(self)
39
+ return update_internal(file, content)
40
+ end
41
+ end
34
42
  end
@@ -1,9 +1,9 @@
1
- module MultiRepo
2
- class TrackingFile
3
- def self.update_internal(file, new_content)
4
- old_content = File.exists?(file) ? File.read(file) : nil
5
- File.write(file, new_content)
6
- return new_content != old_content
7
- end
8
- end
1
+ module MultiRepo
2
+ class TrackingFile
3
+ def update_internal(file, new_content)
4
+ old_content = File.exists?(file) ? File.read(file) : nil
5
+ File.write(file, new_content)
6
+ return new_content != old_content
7
+ end
8
+ end
9
9
  end
@@ -1,44 +1,42 @@
1
- require "multirepo/git/git"
2
- require_relative "meta-file"
3
- require_relative "lock-file"
4
-
5
- module MultiRepo
6
- class TrackingFiles
7
- FILE_CLASSES = [MetaFile, LockFile]
8
-
9
- def self.update
10
- updated = false
11
- FILE_CLASSES.each do |file_class|
12
- updated |= file_class.update
13
- end
14
- return updated
15
- end
16
-
17
- def self.stage
18
- Git.run_in_current_dir("add --force -- #{files_pathspec}", Runner::Verbosity::OUTPUT_ON_ERROR)
19
- end
20
-
21
- def self.commit(message)
22
- stage
23
-
24
- output = Git.run_in_current_dir("ls-files --modified --others -- #{files_pathspec}", Runner::Verbosity::NEVER_OUTPUT)
25
- files_are_untracked_or_modified = output.strip != ""
26
-
27
- output = Git.run_in_current_dir("diff --name-only --cached -- #{files_pathspec}", Runner::Verbosity::NEVER_OUTPUT)
28
- files_are_staged = output.strip != ""
29
-
30
- must_commit = files_are_untracked_or_modified || files_are_staged
31
- Git.run_in_current_dir("commit -m \"#{message}\" --only -- #{files_pathspec}", Runner::Verbosity::OUTPUT_ON_ERROR) if must_commit
32
-
33
- return must_commit
34
- end
35
-
36
- def self.delete
37
- FILE_CLASSES.each { |c| FileUtils.rm_f(c::FILENAME) }
38
- end
39
-
40
- def self.files_pathspec
41
- FILE_CLASSES.map{ |c| c::FILENAME }.join(" ")
42
- end
43
- end
1
+ require "multirepo/git/git"
2
+ require_relative "meta-file"
3
+ require_relative "lock-file"
4
+
5
+ module MultiRepo
6
+ class TrackingFiles
7
+ FILES = [MetaFile.new("."), LockFile.new(".")]
8
+
9
+ def self.update
10
+ updated = false
11
+ FILES.each { |f| updated |= f.update }
12
+ return updated
13
+ end
14
+
15
+ def self.stage
16
+ Git.run_in_current_dir("add --force -- #{files_pathspec}", Runner::Verbosity::OUTPUT_ON_ERROR)
17
+ end
18
+
19
+ def self.commit(message)
20
+ stage
21
+
22
+ output = Git.run_in_current_dir("ls-files --modified --others -- #{files_pathspec}", Runner::Verbosity::OUTPUT_NEVER)
23
+ files_are_untracked_or_modified = output.strip != ""
24
+
25
+ output = Git.run_in_current_dir("diff --name-only --cached -- #{files_pathspec}", Runner::Verbosity::OUTPUT_NEVER)
26
+ files_are_staged = output.strip != ""
27
+
28
+ must_commit = files_are_untracked_or_modified || files_are_staged
29
+ Git.run_in_current_dir("commit -m \"#{message}\" --only -- #{files_pathspec}", Runner::Verbosity::OUTPUT_ON_ERROR) if must_commit
30
+
31
+ return must_commit
32
+ end
33
+
34
+ def self.delete
35
+ FILES.each { |f| FileUtils.rm_f(f.file) }
36
+ end
37
+
38
+ def self.files_pathspec
39
+ FILES.map{ |f| f.file }.join(" ")
40
+ end
41
+ end
44
42
  end
@@ -1,28 +1,28 @@
1
- require_relative "git"
2
-
3
- module MultiRepo
4
- class Branch
5
- attr_accessor :name
6
-
7
- def initialize(repo, name)
8
- @repo = repo
9
- @name = name
10
- end
11
-
12
- def exists?
13
- lines = Git.run_in_working_dir(@repo.path, "branch", Runner::Verbosity::NEVER_OUTPUT).split("\n")
14
- branch_names = lines.map { |line| line.tr("* ", "")}
15
- branch_names.include?(@name)
16
- end
17
-
18
- def create(remote_tracking = false)
19
- Git.run_in_working_dir(@repo.path, "branch #{@name}", Runner::Verbosity::OUTPUT_ON_ERROR)
20
- Git.run_in_working_dir(@repo.path, "push -u origin #{name}", Runner::Verbosity::OUTPUT_ON_ERROR) if remote_tracking
21
- end
22
-
23
- def checkout
24
- Git.run_in_working_dir(@repo.path, "checkout #{@name}", Runner::Verbosity::OUTPUT_ON_ERROR)
25
- Git.last_command_succeeded
26
- end
27
- end
1
+ require_relative "git"
2
+
3
+ module MultiRepo
4
+ class Branch
5
+ attr_accessor :name
6
+
7
+ def initialize(repo, name)
8
+ @repo = repo
9
+ @name = name
10
+ end
11
+
12
+ def exists?
13
+ lines = Git.run_in_working_dir(@repo.path, "branch", Runner::Verbosity::OUTPUT_NEVER).split("\n")
14
+ branch_names = lines.map { |line| line.tr("* ", "")}
15
+ branch_names.include?(@name)
16
+ end
17
+
18
+ def create(remote_tracking = false)
19
+ Git.run_in_working_dir(@repo.path, "branch #{@name}", Runner::Verbosity::OUTPUT_ON_ERROR)
20
+ Git.run_in_working_dir(@repo.path, "push -u origin #{name}", Runner::Verbosity::OUTPUT_ON_ERROR) if remote_tracking
21
+ end
22
+
23
+ def checkout
24
+ Git.run_in_working_dir(@repo.path, "checkout #{@name}", Runner::Verbosity::OUTPUT_ON_ERROR)
25
+ Git.last_command_succeeded
26
+ end
27
+ end
28
28
  end
@@ -1,11 +1,11 @@
1
- module MultiRepo
2
- class Change
3
- attr_accessor :status
4
- attr_accessor :path
5
-
6
- def initialize(line)
7
- @status = line[0...2].strip
8
- @path = line[3..-1]
9
- end
10
- end
1
+ module MultiRepo
2
+ class Change
3
+ attr_accessor :status
4
+ attr_accessor :path
5
+
6
+ def initialize(line)
7
+ @status = line[0...2].strip
8
+ @path = line[3..-1]
9
+ end
10
+ end
11
11
  end
@@ -1,18 +1,18 @@
1
- require_relative "git"
2
-
3
- module MultiRepo
4
- class Commit
5
- attr_accessor :ref
6
-
7
- def initialize(repo, ref)
8
- @repo = repo
9
- @ref = ref
10
- end
11
-
12
- def is_merge?
13
- lines = Git.run_in_working_dir(@repo.path, "cat-file -p #{@ref}", Runner::Verbosity::NEVER_OUTPUT).split("\n")
14
- parents = lines.grep(/^parent /)
15
- return parents.count > 1
16
- end
17
- end
1
+ require_relative "git"
2
+
3
+ module MultiRepo
4
+ class Commit
5
+ attr_accessor :ref
6
+
7
+ def initialize(repo, ref)
8
+ @repo = repo
9
+ @ref = ref
10
+ end
11
+
12
+ def is_merge?
13
+ lines = Git.run_in_working_dir(@repo.path, "cat-file -p #{@ref}", Runner::Verbosity::OUTPUT_NEVER).split("\n")
14
+ parents = lines.grep(/^parent /)
15
+ return parents.count > 1
16
+ end
17
+ end
18
18
  end
@@ -1,40 +1,40 @@
1
- require "multirepo/utility/runner"
2
- require "multirepo/git/git"
3
- require "multirepo/config"
4
-
5
- module MultiRepo
6
- class Git
7
- class << self
8
- attr_accessor :last_command_succeeded
9
- end
10
-
11
- def self.run_in_current_dir(git_command, verbosity)
12
- full_command = "#{git_executable} #{git_command}"
13
- run(full_command, verbosity)
14
- end
15
-
16
- def self.run_in_working_dir(path, git_command, verbosity)
17
- full_command = "#{git_executable} -C \"#{path}\" #{git_command}";
18
-
19
- # True fix for the -C flag issue in pre-commit hook where the status command would
20
- # fail to provide correct results if a pathspec was provided when performing a commit.
21
- # http://thread.gmane.org/gmane.comp.version-control.git/263319/focus=263323
22
-
23
- if Config.instance.running_git_hook
24
- full_command = "sh -c 'unset $(git rev-parse --local-env-vars); #{full_command};'"
25
- end
26
-
27
- run(full_command, verbosity)
28
- end
29
-
30
- def self.run(full_command, verbosity)
31
- result = Runner.run(full_command, verbosity)
32
- @last_command_succeeded = Runner.last_command_succeeded
33
- return result
34
- end
35
-
36
- def self.git_executable
37
- Config.instance.git_executable || "git"
38
- end
39
- end
1
+ require "multirepo/utility/runner"
2
+ require "multirepo/git/git"
3
+ require "multirepo/config"
4
+
5
+ module MultiRepo
6
+ class Git
7
+ class << self
8
+ attr_accessor :last_command_succeeded
9
+ end
10
+
11
+ def self.run_in_current_dir(git_command, verbosity)
12
+ full_command = "#{git_executable} #{git_command}"
13
+ run(full_command, verbosity)
14
+ end
15
+
16
+ def self.run_in_working_dir(path, git_command, verbosity)
17
+ full_command = "#{git_executable} -C \"#{path}\" #{git_command}";
18
+
19
+ # True fix for the -C flag issue in pre-commit hook where the status command would
20
+ # fail to provide correct results if a pathspec was provided when performing a commit.
21
+ # http://thread.gmane.org/gmane.comp.version-control.git/263319/focus=263323
22
+
23
+ if Config.instance.running_git_hook
24
+ full_command = "sh -c 'unset $(git rev-parse --local-env-vars); #{full_command};'"
25
+ end
26
+
27
+ run(full_command, verbosity)
28
+ end
29
+
30
+ def self.run(full_command, verbosity)
31
+ result = Runner.run(full_command, verbosity)
32
+ @last_command_succeeded = Runner.last_command_succeeded
33
+ return result
34
+ end
35
+
36
+ def self.git_executable
37
+ Config.instance.git_executable || "git"
38
+ end
39
+ end
40
40
  end
@@ -1,17 +1,17 @@
1
- require_relative "git"
2
-
3
- module MultiRepo
4
- class Remote
5
- attr_accessor :name
6
-
7
- def initialize(repo, name)
8
- @repo = repo
9
- @name = name
10
- end
11
-
12
- def url
13
- output = Git.run_in_working_dir(@repo.path, "config --get remote.#{@name}.url", Runner::Verbosity::NEVER_OUTPUT).strip
14
- return output == "" ? nil : output
15
- end
16
- end
1
+ require_relative "git"
2
+
3
+ module MultiRepo
4
+ class Remote
5
+ attr_accessor :name
6
+
7
+ def initialize(repo, name)
8
+ @repo = repo
9
+ @name = name
10
+ end
11
+
12
+ def url
13
+ output = Git.run_in_working_dir(@repo.path, "config --get remote.#{@name}.url", Runner::Verbosity::OUTPUT_NEVER).strip
14
+ return output == "" ? nil : output
15
+ end
16
+ end
17
17
  end
@@ -1,78 +1,78 @@
1
- require_relative "branch"
2
- require_relative "remote"
3
- require_relative "commit"
4
- require_relative "change"
5
-
6
- module MultiRepo
7
- class Repo
8
- attr_accessor :path
9
- attr_accessor :basename
10
-
11
- def initialize(path)
12
- @path = path
13
- @basename = Pathname.new(path).basename.to_s
14
- end
15
-
16
- # Inspection
17
-
18
- def exists?
19
- return false unless Dir.exist?("#{@path}/.git")
20
- return Git.run_in_working_dir(@path, "rev-parse --is-inside-work-tree", Runner::Verbosity::NEVER_OUTPUT).strip == "true"
21
- end
22
-
23
- def head_born?
24
- result = Git.run_in_working_dir(@path, "rev-parse HEAD --", Runner::Verbosity::NEVER_OUTPUT).strip
25
- return !result.start_with?("fatal: bad revision")
26
- end
27
-
28
- def current_branch
29
- branch = Git.run_in_working_dir(@path, "rev-parse --abbrev-ref HEAD", Runner::Verbosity::NEVER_OUTPUT).strip
30
- branch != "HEAD" ? branch : nil
31
- end
32
-
33
- def head_hash
34
- Git.run_in_working_dir(@path, "rev-parse HEAD", Runner::Verbosity::NEVER_OUTPUT).strip
35
- end
36
-
37
- def changes
38
- output = Git.run_in_working_dir(@path, "status --porcelain", Runner::Verbosity::NEVER_OUTPUT)
39
- lines = output.split("\n").each{ |f| f.strip }.delete_if{ |f| f == "" }
40
- lines.map { |l| Change.new(l) }
41
- end
42
-
43
- def is_clean?
44
- return changes.count == 0
45
- end
46
-
47
- # Operations
48
-
49
- def fetch
50
- Git.run_in_working_dir(@path, "fetch --progress", Runner::Verbosity::ALWAYS_OUTPUT)
51
- Runner.last_command_succeeded
52
- end
53
-
54
- def clone(url)
55
- Git.run_in_current_dir("clone #{url} #{@path} --progress", Runner::Verbosity::ALWAYS_OUTPUT)
56
- Runner.last_command_succeeded
57
- end
58
-
59
- def checkout(ref)
60
- Git.run_in_working_dir(@path, "checkout #{ref}", Runner::Verbosity::OUTPUT_ON_ERROR)
61
- Runner.last_command_succeeded
62
- end
63
-
64
- # Remotes and branches
65
-
66
- def branch(name)
67
- Branch.new(self, name)
68
- end
69
-
70
- def remote(name)
71
- Remote.new(self, name)
72
- end
73
-
74
- def commit(ref)
75
- Commit.new(self, ref)
76
- end
77
- end
1
+ require_relative "branch"
2
+ require_relative "remote"
3
+ require_relative "commit"
4
+ require_relative "change"
5
+
6
+ module MultiRepo
7
+ class Repo
8
+ attr_accessor :path
9
+ attr_accessor :basename
10
+
11
+ def initialize(path)
12
+ @path = path
13
+ @basename = Pathname.new(path).basename.to_s
14
+ end
15
+
16
+ # Inspection
17
+
18
+ def exists?
19
+ return false unless Dir.exist?("#{@path}/.git")
20
+ return Git.run_in_working_dir(@path, "rev-parse --is-inside-work-tree", Runner::Verbosity::OUTPUT_NEVER).strip == "true"
21
+ end
22
+
23
+ def head_born?
24
+ result = Git.run_in_working_dir(@path, "rev-parse HEAD --", Runner::Verbosity::OUTPUT_NEVER).strip
25
+ return !result.start_with?("fatal: bad revision")
26
+ end
27
+
28
+ def current_branch
29
+ branch = Git.run_in_working_dir(@path, "rev-parse --abbrev-ref HEAD", Runner::Verbosity::OUTPUT_NEVER).strip
30
+ branch != "HEAD" ? branch : nil
31
+ end
32
+
33
+ def head_hash
34
+ Git.run_in_working_dir(@path, "rev-parse HEAD", Runner::Verbosity::OUTPUT_NEVER).strip
35
+ end
36
+
37
+ def changes
38
+ output = Git.run_in_working_dir(@path, "status --porcelain", Runner::Verbosity::OUTPUT_NEVER)
39
+ lines = output.split("\n").each{ |f| f.strip }.delete_if{ |f| f == "" }
40
+ lines.map { |l| Change.new(l) }
41
+ end
42
+
43
+ def clean?
44
+ return changes.count == 0
45
+ end
46
+
47
+ # Operations
48
+
49
+ def fetch
50
+ Git.run_in_working_dir(@path, "fetch --progress", Runner::Verbosity::OUTPUT_ALWAYS)
51
+ Runner.last_command_succeeded
52
+ end
53
+
54
+ def clone(url)
55
+ Git.run_in_current_dir("clone #{url} #{@path} --progress", Runner::Verbosity::OUTPUT_ALWAYS)
56
+ Runner.last_command_succeeded
57
+ end
58
+
59
+ def checkout(ref)
60
+ Git.run_in_working_dir(@path, "checkout #{ref}", Runner::Verbosity::OUTPUT_ON_ERROR)
61
+ Runner.last_command_succeeded
62
+ end
63
+
64
+ # Remotes and branches
65
+
66
+ def branch(name)
67
+ Branch.new(self, name)
68
+ end
69
+
70
+ def remote(name)
71
+ Remote.new(self, name)
72
+ end
73
+
74
+ def commit(ref)
75
+ Commit.new(self, ref)
76
+ end
77
+ end
78
78
  end