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.
- checksums.yaml +7 -0
- data/CHANGELOG +40 -0
- data/README.md +3 -0
- data/Rakefile +56 -0
- data/bin/rim +3 -0
- data/lib/rim/command/command.rb +37 -0
- data/lib/rim/command/status.rb +110 -0
- data/lib/rim/command/sync.rb +69 -0
- data/lib/rim/command/upload.rb +33 -0
- data/lib/rim/command_helper.rb +119 -0
- data/lib/rim/dirty_check.rb +111 -0
- data/lib/rim/file_helper.rb +58 -0
- data/lib/rim/file_logger.rb +21 -0
- data/lib/rim/git.rb +339 -0
- data/lib/rim/manifest/helper.rb +82 -0
- data/lib/rim/manifest/json_reader.rb +40 -0
- data/lib/rim/manifest/manifest.json +7 -0
- data/lib/rim/manifest/model.rb +33 -0
- data/lib/rim/manifest/repo_reader.rb +61 -0
- data/lib/rim/module_helper.rb +52 -0
- data/lib/rim/module_info.rb +30 -0
- data/lib/rim/processor.rb +126 -0
- data/lib/rim/rev_status.rb +61 -0
- data/lib/rim/rim.rb +93 -0
- data/lib/rim/rim_exception.rb +15 -0
- data/lib/rim/rim_info.rb +129 -0
- data/lib/rim/status_builder.rb +219 -0
- data/lib/rim/sync_helper.rb +121 -0
- data/lib/rim/sync_module_helper.rb +115 -0
- data/lib/rim/upload_helper.rb +67 -0
- data/lib/rim/upload_module_helper.rb +152 -0
- data/lib/rim/version.rb +10 -0
- data/test/dirty_check_test.rb +210 -0
- data/test/file_helper_test.rb +132 -0
- data/test/git_test.rb +49 -0
- data/test/manifest_helper_test.rb +29 -0
- data/test/manifest_test_dir/manifest.rim +9 -0
- data/test/manifest_test_dir/subdir/only_to_keep_folder_in_git.txt +0 -0
- data/test/processor_test.rb +32 -0
- data/test/rim_info_test.rb +93 -0
- data/test/status_builder_test.rb +488 -0
- data/test/sync_helper_test.rb +193 -0
- data/test/sync_module_helper_test.rb +96 -0
- data/test/test_helper.rb +39 -0
- data/test/unit_tests.rb +14 -0
- data/test/upload_helper_test.rb +338 -0
- data/test/upload_module_helper_test.rb +92 -0
- 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
|