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,82 @@
1
+ require 'monitor'
2
+ require 'pathname'
3
+
4
+ module RIM
5
+ module Manifest
6
+
7
+ class RimError < StandardError
8
+ def self.status_code(code)
9
+ define_method(:status_code) { code }
10
+ end
11
+ end
12
+
13
+ class ManifestFileNotFound < RimError; status_code(10) ; end
14
+
15
+ module Helpers
16
+ CHDIR_MONITOR = Monitor.new
17
+ CONFIG_FILE_NAME = "manifest.rim"
18
+
19
+ def default_manifest
20
+ manifest = find_manifest
21
+ raise ManifestFileNotFound, "Could not locate #{CONFIG_FILE_NAME}" unless manifest
22
+ Pathname.new(manifest)
23
+ end
24
+
25
+ def default_lockfile
26
+ manifest = default_manifest
27
+ Pathname.new(manifest.sub(/.rim$/, '.locked'))
28
+ end
29
+
30
+ def in_rim_project?
31
+ find_manifest
32
+ end
33
+
34
+ def chdir_monitor
35
+ CHDIR_MONITOR
36
+ end
37
+
38
+ def chdir(dir, &blk)
39
+ chdir_monitor.synchronize do
40
+ Dir.chdir dir, &blk
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def find_manifest
47
+ given = ENV['RIM_MANIFEST']
48
+ return given if given && !given.empty?
49
+
50
+ find_file(CONFIG_FILE_NAME)
51
+ end
52
+
53
+ def find_file(*names)
54
+ search_up(*names) {|filename|
55
+ return filename if File.file?(filename)
56
+ }
57
+ end
58
+
59
+ def find_directory(*names)
60
+ search_up(*names) do |dirname|
61
+ return dirname if File.directory?(dirname)
62
+ end
63
+ end
64
+
65
+ def search_up(*names)
66
+ previous = nil
67
+ current = File.expand_path(Dir.pwd)
68
+
69
+ until !File.directory?(current) || current == previous
70
+ names.each do |name|
71
+ filename = File.join(current, name)
72
+ yield filename
73
+ end
74
+ current, previous = File.expand_path("..", current), current
75
+ end
76
+ end
77
+ extend self
78
+ end
79
+
80
+ end # Manifest
81
+ end # RIM
82
+
@@ -0,0 +1,40 @@
1
+ require 'json'
2
+ require 'csv'
3
+ require 'rim/manifest/model'
4
+
5
+ class RimError < StandardError
6
+ def self.status_code(code)
7
+ define_method(:status_code) { code }
8
+ end
9
+ end
10
+
11
+ class ManifestFileNotFound < RimError; status_code(10) ; end
12
+
13
+ module RIM
14
+ module Manifest
15
+
16
+ def read_manifest(f)
17
+ raise "no manifest found" unless f
18
+ parse_manifest(File.read(f))
19
+ end
20
+
21
+ def parse_manifest(json)
22
+ data_hash = JSON.parse(json)
23
+ modules = []
24
+ if data_hash.has_key?("modules")
25
+ data_hash["modules"].each do |mod|
26
+ modules.push(
27
+ Module.new(
28
+ :remote_path => mod["remote_path"],
29
+ :local_path => mod["local_path"],
30
+ :target_revision => mod["target_revision"],
31
+ :ignores => mod["ignores"]
32
+ ))
33
+ end
34
+ end
35
+ Manifest.new(data_hash["remote_url"], modules)
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,7 @@
1
+ {
2
+ "remote_url" : "ssh://gerrit",
3
+ "modules" : [
4
+ {"local_path": "./bsw/nvStorage", "remote_path": "bsw/modules/nvStorage", "target_revision": "1.1"},
5
+ {"local_path": "./bsw/eepromManager", "remote_path":"bsw/modules/eepromManager", "target_revision": "1.0"}
6
+ ]
7
+ }
@@ -0,0 +1,33 @@
1
+ module RIM
2
+ module Manifest
3
+
4
+ class Manifest
5
+
6
+ attr_reader :remote_url
7
+ attr_reader :modules
8
+
9
+ def initialize(remote_url, modules)
10
+ @remote_url = remote_url
11
+ @modules = modules
12
+ end
13
+
14
+ end
15
+
16
+ class Module
17
+ attr_reader :remote_path
18
+ attr_reader :local_path
19
+ attr_reader :target_revision
20
+ attr_reader :ignores
21
+
22
+ def initialize(args = {})
23
+ @remote_path = args[:remote_path]
24
+ @local_path = args[:local_path]
25
+ @target_revision = args[:target_revision]
26
+ @ignores = args[:ignores]
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
@@ -0,0 +1,61 @@
1
+ require 'nokogiri'
2
+ require 'rim/manifest/model'
3
+
4
+ module RIM
5
+ module Manifest
6
+
7
+ # Reader for the original Google Repo manifest
8
+ class RepoReader
9
+
10
+ def read(file)
11
+ manifest = Manifest.new
12
+ File.open(file) do |f|
13
+ doc = Nokogiri::XML::Document.parse(f)
14
+ remote_by_name = {}
15
+ defaults = nil
16
+ doc.xpath("/manifest/default").each do |d|
17
+ raise "duplicate default setting" if defaults
18
+ defaults = {
19
+ :revision => d.attr("revision"),
20
+ :remote => d.attr("remote")
21
+ }
22
+ end
23
+ doc.xpath("/manifest/remote").each do |r|
24
+ name = r.attr("name")
25
+ raise "remote without a name" unless name
26
+ rem = Remote.new(
27
+ :fetch_url => r.attr("fetch"),
28
+ :review_url => r.attr("review")
29
+ )
30
+ raise "conflicting remote name #{name}" if remote_by_name[name]
31
+ remote_by_name[name] = rem
32
+ end
33
+ doc.xpath("/manifest/project").each do |p|
34
+ remote = p.attr("remote")
35
+ remote ||= defaults[:remote]
36
+ if remote
37
+ raise "remote #{remote} not found" unless remote_by_name[remote]
38
+ else
39
+ raise "no remote specified and no default remote either"
40
+ end
41
+ revision = p.attr("revision")
42
+ revision ||= defaults[:revision]
43
+ if !revision
44
+ raise "no revision specified and no default revision either"
45
+ end
46
+ mod = Module.new(
47
+ :remote_path => p.attr("name"),
48
+ :local_path => p.attr("path"),
49
+ :revision => revision,
50
+ :remote => remote_by_name[remote]
51
+ )
52
+ manifest.add_module(mod)
53
+ end
54
+ end
55
+ manifest
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,52 @@
1
+ require 'rim/processor'
2
+ require 'rim/rim_exception'
3
+ require 'rim/rim_info'
4
+ require 'rim/file_helper'
5
+ require 'rim/dirty_check'
6
+
7
+ module RIM
8
+
9
+ class ModuleHelper < Processor
10
+
11
+ def initialize(workspace_root, module_info, logger)
12
+ super(workspace_root, logger)
13
+ @module_info = module_info
14
+ @remote_url = get_absolute_remote_url(@module_info.remote_url)
15
+ @remote_path = remote_path(@module_info.remote_url)
16
+ @logger = logger
17
+ end
18
+
19
+ protected
20
+
21
+ # fetch module +mod+ into the .rim folder
22
+ # works both for initial fetch and updates
23
+ def fetch_module
24
+ git_path = module_git_path(@remote_path)
25
+ FileUtils.mkdir_p git_path
26
+ RIM::git_session(git_path) do |s|
27
+ if !File.exist?(git_path + "/config")
28
+ s.execute("git clone --mirror #{@remote_url} #{git_path}") do |out, e|
29
+ raise RimException.new("Remote repository '#{@remote_url}' of module '#{@module_info.local_path}' not found.") if e
30
+ end
31
+ else
32
+ s.execute("git remote update")
33
+ end
34
+ end
35
+ git_path
36
+ end
37
+
38
+ # prepare empty folder: remove all files not on the ignore list and empty folders
39
+ def prepare_empty_folder(local_path, ignores)
40
+ ignores = FileHelper.find_matching_files(local_path, true, ignores)
41
+ FileHelper.find_matching_files(local_path, true, "/**/*", File::FNM_DOTMATCH).each do |f|
42
+ if File.file?(f) && !ignores.include?(f)
43
+ FileUtils.rm(f)
44
+ end
45
+ end
46
+ FileHelper.remove_empty_dirs(local_path)
47
+ FileUtils.mkdir_p(local_path)
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,30 @@
1
+ module RIM
2
+
3
+ class ModuleInfo
4
+ # remote url (unique identifier of module)
5
+ attr_reader :remote_url
6
+ # remote branch format
7
+ attr_reader :remote_branch_format
8
+ # locale module path
9
+ attr_reader :local_path
10
+ # target revision
11
+ attr_reader :target_revision
12
+ # ignores
13
+ attr_reader :ignores
14
+
15
+ def initialize(remote_url, local_path, target_revision, ignores = nil, remote_branch_format = nil)
16
+ @remote_url = remote_url
17
+ @remote_branch_format = remote_branch_format
18
+ @local_path = local_path
19
+ @target_revision = target_revision
20
+ if ignores.is_a?(String)
21
+ @ignores = ignores.split(",").each do |s|
22
+ s.strip!
23
+ end
24
+ else
25
+ @ignores = ignores || []
26
+ end
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,126 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+ require 'rim/file_helper'
4
+ require 'rim/git'
5
+ require 'rim/rim_exception'
6
+ require 'rake'
7
+ require 'pathname'
8
+ require 'uri'
9
+
10
+ module RIM
11
+
12
+ class Processor
13
+
14
+ MaxThreads = 10
15
+ GerritServer = "ssh://gerrit/"
16
+
17
+ def initialize(workspace_root, logger)
18
+ @ws_root = workspace_root
19
+ @logger = logger
20
+ end
21
+
22
+ def module_git_path(remote_path)
23
+ # remote url without protocol specifier
24
+ # this way the local path should be unique
25
+ File.join(@ws_root, ".rim", remote_path)
26
+ end
27
+
28
+ def module_tmp_git_path(remote_path)
29
+ # remote url without protocol specifier
30
+ # this way the local path should be unique
31
+ File.join(@ws_root, ".rim", ".tmp", remote_path)
32
+ end
33
+
34
+ def remote_path(remote_url)
35
+ remote_url.
36
+ # protocol specifier, e.g. ssh://
37
+ sub(/^\w+:\/\//,'').
38
+ # windows drive letter
39
+ sub(/^\w+:/,'\1').
40
+ # make sure we don't .. up in a filesystem
41
+ gsub(/\.\.[\\\/]/,'')
42
+ end
43
+
44
+ def get_relative_path(path)
45
+ FileHelper.get_relative_path(path, @ws_root)
46
+ end
47
+
48
+ def get_absolute_remote_url(remote_url)
49
+ if remote_url.start_with?("file:")
50
+ remote_url = remote_url.gsub(/^file:(\/\/)?/, "")
51
+ match = remote_url.match(/^\/(\w)\|/)
52
+ if match
53
+ remote_url = "#{match[1]}:#{remote_url[match[0].size..-1]}"
54
+ elsif !remote_url.start_with?(File::SEPARATOR)
55
+ File.expand_path(remote_url, @ws_root)
56
+ else
57
+ remote_url
58
+ end
59
+ else
60
+ URI.parse(GerritServer).merge(URI.parse(remote_url)).to_s
61
+ end
62
+ end
63
+
64
+ def local_changes?(ws_dir, dir=ws_dir)
65
+ stat = nil
66
+ RIM::git_session(ws_dir) do |s|
67
+ stat = s.status(dir)
68
+ end
69
+ stat.lines.all?{|l| l.ignored?}
70
+ end
71
+
72
+ def clone_or_fetch_repository(remote_url, local_path, clone_log = nil)
73
+ FileUtils.mkdir_p local_path
74
+ RIM::git_session(local_path) do |s|
75
+ if !File.exist?(File.join(local_path, ".git"))
76
+ @logger.info(clone_log) if clone_log
77
+ FileHelper.make_empty_dir(local_path)
78
+ s.execute("git clone #{remote_url} .")
79
+ s.execute("git config core.ignorecase false")
80
+ else
81
+ s.execute("git remote set-url origin #{remote_url}") if !s.has_valid_remote_repository?()
82
+ s.execute("git fetch")
83
+ end
84
+ end
85
+ local_path
86
+ end
87
+
88
+ def each_module_parallel(task_desc, modules)
89
+ if !modules.empty?
90
+ @logger.debug "starting \"#{task_desc}\" for #{modules.size} modules\r"
91
+ threads = []
92
+ messages = []
93
+ i = 0
94
+ done = 0
95
+ while i == 0 || !threads.empty?
96
+ while threads.size < MaxThreads && i < modules.size
97
+ threads << Thread.new(i) do |i|
98
+ begin
99
+ yield(modules[i], i)
100
+ rescue RimException => e
101
+ messages += e.messages
102
+ end
103
+ end
104
+ i += 1
105
+ end
106
+ sleep(0.1)
107
+ threads = threads.select{|t|
108
+ if t.alive?
109
+ true
110
+ else
111
+ t.join
112
+ done += 1
113
+ @logger.debug "#{task_desc} #{done}/#{modules.size}\r"
114
+ false
115
+ end
116
+ }
117
+ end
118
+ if !messages.empty?
119
+ raise RimException.new(messages)
120
+ end
121
+ end
122
+ end
123
+
124
+ end
125
+
126
+ end
@@ -0,0 +1,61 @@
1
+ module RIM
2
+
3
+ # RIM revision status object.
4
+ #
5
+ # Revision status objects hold the RIM status of a specific project git revision.
6
+ # As a special case, this could also be the status of the current working copy.
7
+ #
8
+ # The revision status consists of a set of module status objects,
9
+ # one for each module known to RIM in that revision.
10
+ # The module status points to a RimInfo object holding attribute values
11
+ # valid for that specific revision as well as the current dirty state as
12
+ # calculated by DirtyCheck and the module directory.
13
+ #
14
+ # Revsion status objects can have parent status objects. This way,
15
+ # chains and even trees of status objects can be built. For example in
16
+ # case of a merge commit, the corresponding status object would have
17
+ # two parent status objects, one for each parent git commit.
18
+ #
19
+ class RevStatus
20
+ # git revision (sha1) for which this status was created
21
+ # or nil if the status wasn't created for a git revision
22
+ attr_reader :git_rev
23
+ # module status objects
24
+ attr_reader :modules
25
+ # references to RevStatus objects of parent commits
26
+ attr_reader :parents
27
+
28
+ class ModuleStatus
29
+ # module directory, relative to project dir root
30
+ attr_reader :dir
31
+ # reference to a RimInfo object
32
+ attr_reader :rim_info
33
+
34
+ # dirty state [true, false]
35
+ def dirty?
36
+ @dirty
37
+ end
38
+
39
+ def initialize(dir, rim_info, dirty)
40
+ @dir = dir
41
+ @rim_info = rim_info
42
+ @dirty = dirty
43
+ end
44
+ end
45
+
46
+ def initialize(modules)
47
+ @modules = modules
48
+ @parents = []
49
+ end
50
+
51
+ def dirty?
52
+ modules.any?{|m| m.dirty?}
53
+ end
54
+
55
+ def git_rev=(rev)
56
+ @git_rev = rev
57
+ end
58
+
59
+ end
60
+
61
+ end