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,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