esr-rim 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
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