esr-rim 1.1.5

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 (48) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +40 -0
  3. data/README.md +3 -0
  4. data/Rakefile +56 -0
  5. data/bin/rim +3 -0
  6. data/lib/rim/command/command.rb +37 -0
  7. data/lib/rim/command/status.rb +110 -0
  8. data/lib/rim/command/sync.rb +69 -0
  9. data/lib/rim/command/upload.rb +33 -0
  10. data/lib/rim/command_helper.rb +119 -0
  11. data/lib/rim/dirty_check.rb +111 -0
  12. data/lib/rim/file_helper.rb +58 -0
  13. data/lib/rim/file_logger.rb +21 -0
  14. data/lib/rim/git.rb +339 -0
  15. data/lib/rim/manifest/helper.rb +82 -0
  16. data/lib/rim/manifest/json_reader.rb +40 -0
  17. data/lib/rim/manifest/manifest.json +7 -0
  18. data/lib/rim/manifest/model.rb +33 -0
  19. data/lib/rim/manifest/repo_reader.rb +61 -0
  20. data/lib/rim/module_helper.rb +52 -0
  21. data/lib/rim/module_info.rb +30 -0
  22. data/lib/rim/processor.rb +126 -0
  23. data/lib/rim/rev_status.rb +61 -0
  24. data/lib/rim/rim.rb +93 -0
  25. data/lib/rim/rim_exception.rb +15 -0
  26. data/lib/rim/rim_info.rb +129 -0
  27. data/lib/rim/status_builder.rb +219 -0
  28. data/lib/rim/sync_helper.rb +121 -0
  29. data/lib/rim/sync_module_helper.rb +115 -0
  30. data/lib/rim/upload_helper.rb +67 -0
  31. data/lib/rim/upload_module_helper.rb +152 -0
  32. data/lib/rim/version.rb +10 -0
  33. data/test/dirty_check_test.rb +210 -0
  34. data/test/file_helper_test.rb +132 -0
  35. data/test/git_test.rb +49 -0
  36. data/test/manifest_helper_test.rb +29 -0
  37. data/test/manifest_test_dir/manifest.rim +9 -0
  38. data/test/manifest_test_dir/subdir/only_to_keep_folder_in_git.txt +0 -0
  39. data/test/processor_test.rb +32 -0
  40. data/test/rim_info_test.rb +93 -0
  41. data/test/status_builder_test.rb +488 -0
  42. data/test/sync_helper_test.rb +193 -0
  43. data/test/sync_module_helper_test.rb +96 -0
  44. data/test/test_helper.rb +39 -0
  45. data/test/unit_tests.rb +14 -0
  46. data/test/upload_helper_test.rb +338 -0
  47. data/test/upload_module_helper_test.rb +92 -0
  48. metadata +110 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e39178ba7e2f000cec05a0ca417d4064b1c06cb6
4
+ data.tar.gz: e51d10cecfd216dcb0890a5b3a47ab13086c46c4
5
+ SHA512:
6
+ metadata.gz: a09bfcc5ef6fd0138f5c3be1be93c9c19da499cfd6701cf5efc46eafb3c213b047a8aa0e6eb0b6342f42884a65f1913a5776631104f50970bcc30c64167ed9cb
7
+ data.tar.gz: 7941fdf8455ba6ccc8594a89fe17634ad82f3458aee8a56e6871c65834ddbdd17808c18ff58b1d1b2adc60f81d3c71fbd9ad5e8b05510f91039290fe202626eb
@@ -0,0 +1,40 @@
1
+ # 0.1.0
2
+
3
+ * initial version
4
+
5
+ # 0.1.1
6
+
7
+ * take latest clean commit to create rim branch on
8
+ * Avoid additional parameters in message.
9
+
10
+ # 0.1.2
11
+
12
+ * fixed rim status verify clean when remotes are dirty [BS-236]
13
+
14
+ # 0.1.3
15
+
16
+ * made rim status faster
17
+ * fixed rim exception when project git is renamed
18
+
19
+ # 1.0.0
20
+
21
+ * changed checksum calculation, not backward compatible!
22
+ * fixed commits becoming dirty when line ending format changes
23
+ * allow specification of multiple modules on sync and upload
24
+ * fixed sync with create option
25
+ * made printing of working copy status optional
26
+ * major performance improvements
27
+
28
+ # 1.0.1
29
+
30
+ * fixed dirty check to ignore empty directories
31
+
32
+ # 1.0.2
33
+
34
+ * write all logs to temporary file
35
+
36
+ # 1.1.0
37
+
38
+ * added --gerrit option, needed for pushing new branchs to gerrit [BS-202]
39
+ * fixed exception on rim sync after moving working copy [BS-248]
40
+
@@ -0,0 +1,3 @@
1
+ # RIM - Multi git tool
2
+
3
+ RIM lets you work with multiple git repositories from within one single git repository.
@@ -0,0 +1,56 @@
1
+ $:.unshift(File.dirname(__FILE__)+"/lib")
2
+
3
+ require 'rubygems/package_task'
4
+ require 'rdoc/task'
5
+ require 'rim/version'
6
+
7
+ DocFiles = [
8
+ "README.md", "CHANGELOG"
9
+ ]
10
+
11
+ RTextGemSpec = Gem::Specification.new do |s|
12
+ s.name = "esr-rim"
13
+ s.version = RIM::Version::Version
14
+ s.date = Time.now.strftime("%Y-%m-%d")
15
+ s.summary = "RIM - multi git tool"
16
+ s.description = "RIM lets you work with multiple git repositories from within one single git repository."
17
+ s.authors = "ESR Labs AG"
18
+ s.homepage = "http://esrlabs.com"
19
+ s.add_dependency('subcommand', '>= 1.0.6')
20
+ gemfiles = Rake::FileList.new
21
+ gemfiles.include("{lib,test}/**/*")
22
+ gemfiles.include(DocFiles)
23
+ gemfiles.include("Rakefile")
24
+ s.files = gemfiles
25
+ s.rdoc_options = ["--main", "README.md", "-x", "test"]
26
+ s.extra_rdoc_files = DocFiles
27
+ s.bindir = "bin"
28
+ s.executables = ["rim"]
29
+ end
30
+
31
+ RDoc::Task.new do |rd|
32
+ rd.main = "README.md"
33
+ rd.rdoc_files.include(DocFiles)
34
+ rd.rdoc_files.include("lib/**/*.rb")
35
+ rd.rdoc_dir = "doc"
36
+ end
37
+
38
+ RTextPackageTask = Gem::PackageTask.new(RTextGemSpec) do |p|
39
+ p.need_zip = false
40
+ end
41
+
42
+ task :prepare_package_rdoc => :rdoc do
43
+ RTextPackageTask.package_files.include("doc/**/*")
44
+ end
45
+
46
+ desc 'run unit tests'
47
+ task :run_tests do
48
+ sh "ruby test/unit_tests.rb"
49
+ end
50
+
51
+ task :release => [:prepare_package_rdoc, :package]
52
+
53
+ task :clobber => [:clobber_rdoc, :clobber_package]
54
+
55
+ task :default => :run_tests
56
+
data/bin/rim ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rim/rim'
3
+
@@ -0,0 +1,37 @@
1
+ module RIM
2
+ module Command
3
+
4
+ class Command
5
+ attr_writer :logger
6
+
7
+ def initialize(processor)
8
+ @processor = processor
9
+ end
10
+
11
+ def project_git_dir
12
+ git_dir = find_git_dir(".")
13
+ raise RimException.new("The current path is not part of a git repository.") if !git_dir
14
+ git_dir
15
+ end
16
+
17
+ private
18
+
19
+ def find_git_dir(start_dir)
20
+ last_dir = nil
21
+ dir = File.expand_path(start_dir)
22
+ while dir != last_dir
23
+ if File.exist?("#{dir}/.git") || dir =~ /\.git$/
24
+ return dir
25
+ end
26
+ last_dir = dir
27
+ # returns itself on file system root
28
+ dir = File.dirname(dir)
29
+ end
30
+ nil
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+
37
+
@@ -0,0 +1,110 @@
1
+ require 'rim/status_builder'
2
+
3
+ module RIM
4
+ module Command
5
+
6
+ class Status < Command
7
+
8
+ def initialize(opts)
9
+ opts.banner = "Usage: rim status [<options>] [<to-rev>|<from-rev>..<to-rev>]"
10
+ opts.description = "Prints commits and their RIM status"
11
+ opts.separator ""
12
+ opts.separator "Without revision arguments checks the current branch and all local ancestors."
13
+ opts.separator "With a single <to-rev> checks that revision and all local ancestors."
14
+ opts.separator "Otherwise checks <to-rev> and ancestors without <from-rev> and ancestors."
15
+ opts.separator "With the --gerrit option, assumes all yet unknown commits to be 'local'."
16
+ opts.separator ""
17
+ opts.on("-d", "--detailed", "print detailed status") do
18
+ @detailed = true
19
+ end
20
+ opts.on("-w", "--working-copy", "print working copy status") do
21
+ @wc_status = true
22
+ end
23
+ opts.on("-f", "--fast", "fast status assuming remote is clean") do
24
+ @fast = true
25
+ end
26
+ opts.on("--verify-clean", "exit with error code 1 if commits are dirty") do
27
+ @verify_clean = true
28
+ end
29
+ opts.on("--gerrit", "special gerrit mode which stops on all known commits") do
30
+ @gerrit_mode = true
31
+ end
32
+ end
33
+
34
+ def invoke()
35
+ root = project_git_dir
36
+ rev_arg = ARGV.shift
37
+ stat = nil
38
+ RIM.git_session(root) do |gs|
39
+ sb = RIM::StatusBuilder.new
40
+ if @wc_status
41
+ stat = sb.fs_status(root)
42
+ print_status(gs, stat)
43
+ end
44
+ if rev_arg
45
+ if rev_arg =~ /\.\./
46
+ from_rev, to_rev = rev_arg.split("..")
47
+ else
48
+ from_rev, to_rev = nil, rev_arg
49
+ end
50
+ stat = sb.rev_history_status(gs, to_rev, :stop_rev => from_rev, :fast => @fast, :gerrit => @gerrit_mode)
51
+ print_status(gs, stat)
52
+ else
53
+ branch = gs.current_branch_name
54
+ stat = sb.rev_history_status(gs, branch, :fast => @fast)
55
+ print_status(gs, stat)
56
+ end
57
+ end
58
+ if @verify_clean && any_dirty?(stat)
59
+ exit(1)
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def any_dirty?(stat)
66
+ # don't check the last (remote) status nodes (leaves of the status tree)
67
+ # these are normally remote commits which could be dirty
68
+ # the initial commit would also be a leave
69
+ # TODO: see print_status
70
+ stat.dirty? || stat.parents.any?{|p| !p.parents.empty? && any_dirty?(p)}
71
+ end
72
+
73
+ def print_status(gs, stat)
74
+ # don't print the last (remote) status nodes
75
+ # note: this also excludes the initial commit
76
+ # TODO: make sure to print the first commit
77
+ # otherwise the first could be dirty but won't be shown to the user
78
+ return if stat.git_rev && stat.parents.empty?
79
+ dirty_mods = stat.modules.select{|m| m.dirty?}
80
+ stat_info = dirty_mods.empty? ? "[ OK]" : "[DIRTY]"
81
+ headline = ""
82
+ if stat.git_rev
83
+ out = gs.execute "git rev-list --format=oneline -n 1 #{stat.git_rev}"
84
+ if out =~ /^(\w+) (.*)/
85
+ sha1, comment = $1, $2
86
+ comment = comment[0..56]+"..." if comment.size > 60
87
+ headline += "#{stat_info} #{sha1[0..6]} #{comment}"
88
+ end
89
+ else
90
+ headline += "#{stat_info} ------- uncommitted changes"
91
+ end
92
+ if @detailed
93
+ @logger.info headline
94
+ dirty_mods.each do |m|
95
+ @logger.info " - #{m.dir}"
96
+ end
97
+ elsif dirty_mods.size > 0
98
+ @logger.info "#{headline} (#{dirty_mods.size} modules dirty)"
99
+ else
100
+ @logger.info headline
101
+ end
102
+ stat.parents.each do |p|
103
+ print_status(gs, p)
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,69 @@
1
+ require 'rim/command/command'
2
+ require 'rim/manifest/helper'
3
+ require 'rim/rim_exception'
4
+ require 'rim/rim_info'
5
+ require 'rim/sync_helper'
6
+ require 'uri'
7
+
8
+ module RIM
9
+ module Command
10
+
11
+ class Sync < Command
12
+
13
+ include RIM::Manifest
14
+
15
+ def initialize(opts)
16
+ opts.banner = "Usage: rim sync [<options>] [<local_module_path>]"
17
+ opts.description = "Synchronize specified rim modules with remote repository revisions."
18
+ opts.separator ""
19
+ opts.on("-m", "--manifest [MANIFEST]", String, "Read information from manifest.", \
20
+ "If no manifest file is specified a 'manifest.rim' file will be used.") do |manifest|
21
+ @manifest = manifest ? manifest : Helpers::default_manifest
22
+ end
23
+ opts.on("-c", "--create", "Synchronize module initially to <local_module_path>.", \
24
+ "Specify the remote URL and the target revision with the options.") do
25
+ @create = true
26
+ end
27
+ @module_options = {}
28
+ opts.on("-u", "--remote-url URL", String, "Set the remote URL of the module.", \
29
+ "A relative path will be applied to ssh://gerrit/") do |url|
30
+ @module_options[:remote_url] = url
31
+ end
32
+ opts.on("-r", "--target-revision REVISION", String, "Set the target revision of the module.") do |target_revision|
33
+ @module_options[:target_revision] = target_revision
34
+ end
35
+ opts.on("-i", "--ignore [PATTERN_LIST]", String, "Set the ignore patterns by specifying a comma separated list.") do |ignores|
36
+ @module_options[:ignores] = ignores || ""
37
+ end
38
+ opts.on("-m", "--message MESSAGE", String, "Message header to provide to each commit.") do |message|
39
+ @message = message
40
+ end
41
+ end
42
+
43
+ def invoke()
44
+ helper = SyncHelper.new(project_git_dir, @logger)
45
+ if @manifest
46
+ helper.modules_from_manifest(@manifest)
47
+ elsif @create
48
+ local_path = ARGV.shift || "."
49
+ if helper.find_file_dir_in_workspace(local_path, RimInfo::InfoFileName)
50
+ raise RimException.new("There's already a module file. Don't use the create option to sync the module.")
51
+ elsif !@module_options[:remote_url] || !@module_options[:target_revision]
52
+ raise RimException.new("Please specify remote URL and target revision for the new module.")
53
+ else
54
+ helper.add_module_info(helper.create_module_info(@module_options[:remote_url], local_path, @module_options[:target_revision], \
55
+ @module_options[:ignores]))
56
+ end
57
+ else
58
+ helper.modules_from_paths(ARGV, @module_options)
59
+ end
60
+ helper.check_arguments
61
+ helper.sync(@message)
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
68
+
69
+
@@ -0,0 +1,33 @@
1
+ require 'rim/command/command'
2
+ require 'rim/processor'
3
+ require 'rim/upload_helper'
4
+
5
+ module RIM
6
+ module Command
7
+
8
+ class Upload < Command
9
+
10
+ include RIM::Manifest
11
+
12
+ def initialize(opts)
13
+ @review = true
14
+ opts.banner = "Usage: rim upload <local_module_path>"
15
+ opts.description = "Upload changes from rim module synchronized to <local_module_path> to remote repository."
16
+ opts.on("-n", "--no-review", "Uploads without review. The changes will be pushed directly to the module's target branch.") do
17
+ @review = false
18
+ end
19
+ end
20
+
21
+ def invoke()
22
+ helper = UploadHelper.new(project_git_dir, @review, @logger)
23
+ helper.modules_from_paths(ARGV)
24
+ helper.check_arguments
25
+ helper.upload
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,119 @@
1
+ require 'rim/file_helper'
2
+ require 'rim/processor'
3
+ require 'rim/module_info'
4
+ require 'rim/rim_info'
5
+ require 'rim/manifest/json_reader'
6
+ require 'rim/status_builder'
7
+
8
+ module RIM
9
+
10
+ class CommandHelper < Processor
11
+
12
+ include Manifest
13
+
14
+ def initialize(workspace_root, logger, module_infos = nil)
15
+ super(workspace_root, logger)
16
+ @paths = []
17
+ @logger = logger
18
+ if module_infos
19
+ module_infos.each do |m|
20
+ add_module_info(m)
21
+ end
22
+ end
23
+ end
24
+
25
+ # check whether workspace is not touched
26
+ def check_ready
27
+ raise RimException.new("The workspace git contains uncommitted changes.") if !local_changes?(@ws_root)
28
+ end
29
+
30
+ def check_arguments
31
+ raise RimException.new("Unexpected command line arguments.") if !ARGV.empty?
32
+ end
33
+
34
+ def create_module_info(remote_url, local_path, target_revision, ignores)
35
+ ModuleInfo.new(remote_url, get_relative_path(local_path), target_revision, ignores, get_remote_branch_format(remote_url))
36
+ end
37
+
38
+ def modules_from_manifest(path)
39
+ manifest = read_manifest(path)
40
+ manifest.modules.each do |mod|
41
+ add_unique_module_info(create_module_info(mod.remote_path, mod.local_path, mod.target_revision, mod.ignores))
42
+ end
43
+ true
44
+ end
45
+
46
+ def modules_from_paths(paths, opts = {})
47
+ if paths.empty?
48
+ module_from_path(nil, opts)
49
+ elsif paths.length == 1 || opts.empty?
50
+ while !paths.empty?
51
+ module_from_path(paths.shift, opts)
52
+ end
53
+ else
54
+ raise RimException.new("Multiple modules cannot be used with additional options.")
55
+ end
56
+ end
57
+
58
+ def module_from_path(path, opts = {})
59
+ module_path = find_file_dir_in_workspace(path || ".", RimInfo::InfoFileName)
60
+ if module_path
61
+ rim_info = RimInfo.from_dir(module_path)
62
+ add_unique_module_info(create_module_info(opts.has_key?(:remote_url) ? opts[:remote_url] : rim_info.remote_url, \
63
+ module_path, opts.has_key?(:target_revision) ? opts[:target_revision] : rim_info.target_revision, \
64
+ opts.has_key?(:ignores) ? opts[:ignores] : rim_info.ignores))
65
+ module_path
66
+ else
67
+ raise RimException.new(path ? "No module info found in '#{path}'." : "No module info found.")
68
+ end
69
+ end
70
+
71
+ def modules_from_workspace()
72
+ if File.directory?(File.join(@ws_root, ".rim"))
73
+ status = StatusBuilder.new.fs_status(@ws_root)
74
+ status.modules.each do |mod|
75
+ rim_info = mod.rim_info
76
+ add_unique_module_info(ModuleInfo.new(rim_info.remote_url, mod.dir, rim_info.upstream, rim_info.ignores))
77
+ end
78
+ true
79
+ end
80
+ end
81
+
82
+ def add_unique_module_info(module_info)
83
+ if !@paths.include?(module_info.local_path)
84
+ @paths.push(module_info.local_path)
85
+ add_module_info(module_info)
86
+ else
87
+ raise RimException.new("Module '#{module_info.local_path}' specified more than once.")
88
+ end
89
+ end
90
+
91
+ def get_remote_branch_format(remote_url)
92
+ get_absolute_remote_url(remote_url).start_with?(GerritServer) ? "refs/for/%s" : nil
93
+ #"refs/for/%s"
94
+ end
95
+
96
+ def find_file_dir_in_workspace(start_dir, file)
97
+ path = File.expand_path(start_dir)
98
+ while path != @ws_root
99
+ if File.exist?(File.join(path, file))
100
+ return path
101
+ else
102
+ parent = File.dirname(path)
103
+ if parent != path
104
+ path = parent
105
+ else
106
+ break
107
+ end
108
+ end
109
+ end
110
+ nil
111
+ end
112
+
113
+ protected
114
+ def add_module_info(module_info)
115
+ end
116
+
117
+ end
118
+
119
+ end