rosette-core 1.0.1

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 (158) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +26 -0
  3. data/History.txt +3 -0
  4. data/README.md +94 -0
  5. data/Rakefile +18 -0
  6. data/lib/rosette/core.rb +110 -0
  7. data/lib/rosette/core/branch_utils.rb +152 -0
  8. data/lib/rosette/core/commands.rb +139 -0
  9. data/lib/rosette/core/commands/errors.rb +17 -0
  10. data/lib/rosette/core/commands/git/commit_command.rb +65 -0
  11. data/lib/rosette/core/commands/git/diff_base_command.rb +301 -0
  12. data/lib/rosette/core/commands/git/diff_command.rb +188 -0
  13. data/lib/rosette/core/commands/git/diff_entry.rb +44 -0
  14. data/lib/rosette/core/commands/git/fetch_command.rb +27 -0
  15. data/lib/rosette/core/commands/git/repo_snapshot_command.rb +40 -0
  16. data/lib/rosette/core/commands/git/show_command.rb +70 -0
  17. data/lib/rosette/core/commands/git/snapshot_command.rb +50 -0
  18. data/lib/rosette/core/commands/git/status_command.rb +128 -0
  19. data/lib/rosette/core/commands/git/with_non_merge_ref.rb +48 -0
  20. data/lib/rosette/core/commands/git/with_ref.rb +92 -0
  21. data/lib/rosette/core/commands/git/with_refs.rb +92 -0
  22. data/lib/rosette/core/commands/git/with_repo_name.rb +50 -0
  23. data/lib/rosette/core/commands/git/with_snapshots.rb +45 -0
  24. data/lib/rosette/core/commands/queuing/enqueue_commit_command.rb +37 -0
  25. data/lib/rosette/core/commands/queuing/requeue_commit_command.rb +46 -0
  26. data/lib/rosette/core/commands/translations/export_command.rb +257 -0
  27. data/lib/rosette/core/commands/translations/translation_lookup_command.rb +66 -0
  28. data/lib/rosette/core/commands/translations/with_locale.rb +47 -0
  29. data/lib/rosette/core/configurator.rb +160 -0
  30. data/lib/rosette/core/error_reporters/buffered_error_reporter.rb +96 -0
  31. data/lib/rosette/core/error_reporters/error_reporter.rb +31 -0
  32. data/lib/rosette/core/error_reporters/nil_error_reporter.rb +25 -0
  33. data/lib/rosette/core/error_reporters/printing_error_reporter.rb +58 -0
  34. data/lib/rosette/core/error_reporters/raising_error_reporter.rb +27 -0
  35. data/lib/rosette/core/errors.rb +93 -0
  36. data/lib/rosette/core/extractor/commit_log.rb +33 -0
  37. data/lib/rosette/core/extractor/commit_log_status.rb +57 -0
  38. data/lib/rosette/core/extractor/commit_processor.rb +109 -0
  39. data/lib/rosette/core/extractor/extractor.rb +72 -0
  40. data/lib/rosette/core/extractor/extractor_config.rb +74 -0
  41. data/lib/rosette/core/extractor/locale.rb +118 -0
  42. data/lib/rosette/core/extractor/phrase.rb +76 -0
  43. data/lib/rosette/core/extractor/phrase/phrase_index_policy.rb +108 -0
  44. data/lib/rosette/core/extractor/phrase/phrase_to_hash.rb +33 -0
  45. data/lib/rosette/core/extractor/repo_config.rb +339 -0
  46. data/lib/rosette/core/extractor/serializer_config.rb +55 -0
  47. data/lib/rosette/core/extractor/static_extractor.rb +44 -0
  48. data/lib/rosette/core/extractor/translation.rb +44 -0
  49. data/lib/rosette/core/extractor/translation/translation_to_hash.rb +28 -0
  50. data/lib/rosette/core/git/diff_finder.rb +131 -0
  51. data/lib/rosette/core/git/ref.rb +116 -0
  52. data/lib/rosette/core/git/repo.rb +378 -0
  53. data/lib/rosette/core/path_matcher_factory.rb +330 -0
  54. data/lib/rosette/core/resolvers/extractor_id.rb +37 -0
  55. data/lib/rosette/core/resolvers/integration_id.rb +37 -0
  56. data/lib/rosette/core/resolvers/preprocessor_id.rb +38 -0
  57. data/lib/rosette/core/resolvers/resolver.rb +115 -0
  58. data/lib/rosette/core/resolvers/serializer_id.rb +37 -0
  59. data/lib/rosette/core/snapshots/cached_head_snapshot_factory.rb +51 -0
  60. data/lib/rosette/core/snapshots/cached_snapshot_factory.rb +67 -0
  61. data/lib/rosette/core/snapshots/head_snapshot_factory.rb +58 -0
  62. data/lib/rosette/core/snapshots/repo_config_path_filter.rb +83 -0
  63. data/lib/rosette/core/snapshots/snapshot_factory.rb +184 -0
  64. data/lib/rosette/core/string_utils.rb +23 -0
  65. data/lib/rosette/core/translation_status.rb +81 -0
  66. data/lib/rosette/core/validators.rb +18 -0
  67. data/lib/rosette/core/validators/commit_validator.rb +62 -0
  68. data/lib/rosette/core/validators/commits_validator.rb +32 -0
  69. data/lib/rosette/core/validators/encoding_validator.rb +32 -0
  70. data/lib/rosette/core/validators/locale_validator.rb +37 -0
  71. data/lib/rosette/core/validators/repo_validator.rb +33 -0
  72. data/lib/rosette/core/validators/serializer_validator.rb +37 -0
  73. data/lib/rosette/core/validators/validator.rb +31 -0
  74. data/lib/rosette/core/version.rb +8 -0
  75. data/lib/rosette/data_stores.rb +11 -0
  76. data/lib/rosette/data_stores/errors.rb +26 -0
  77. data/lib/rosette/data_stores/phrase_status.rb +59 -0
  78. data/lib/rosette/integrations.rb +12 -0
  79. data/lib/rosette/integrations/errors.rb +15 -0
  80. data/lib/rosette/integrations/integratable.rb +58 -0
  81. data/lib/rosette/integrations/integration.rb +23 -0
  82. data/lib/rosette/preprocessors.rb +11 -0
  83. data/lib/rosette/preprocessors/errors.rb +14 -0
  84. data/lib/rosette/preprocessors/preprocessor.rb +48 -0
  85. data/lib/rosette/queuing.rb +14 -0
  86. data/lib/rosette/queuing/commits.rb +19 -0
  87. data/lib/rosette/queuing/commits/commit_conductor.rb +90 -0
  88. data/lib/rosette/queuing/commits/commit_job.rb +93 -0
  89. data/lib/rosette/queuing/commits/commits_queue_configurator.rb +60 -0
  90. data/lib/rosette/queuing/commits/extract_stage.rb +46 -0
  91. data/lib/rosette/queuing/commits/fetch_stage.rb +51 -0
  92. data/lib/rosette/queuing/commits/finalize_stage.rb +76 -0
  93. data/lib/rosette/queuing/commits/phrase_storage_granularity.rb +20 -0
  94. data/lib/rosette/queuing/commits/push_stage.rb +91 -0
  95. data/lib/rosette/queuing/commits/stage.rb +96 -0
  96. data/lib/rosette/queuing/job.rb +74 -0
  97. data/lib/rosette/queuing/queue.rb +28 -0
  98. data/lib/rosette/queuing/queue_configurator.rb +76 -0
  99. data/lib/rosette/queuing/worker.rb +30 -0
  100. data/lib/rosette/serializers.rb +10 -0
  101. data/lib/rosette/serializers/serializer.rb +98 -0
  102. data/lib/rosette/tms.rb +9 -0
  103. data/lib/rosette/tms/repository.rb +95 -0
  104. data/rosette-core.gemspec +24 -0
  105. data/spec/core/branch_utils_spec.rb +110 -0
  106. data/spec/core/commands/git/commit_command_spec.rb +60 -0
  107. data/spec/core/commands/git/diff_command_spec.rb +263 -0
  108. data/spec/core/commands/git/fetch_command_spec.rb +61 -0
  109. data/spec/core/commands/git/repo_snapshot_command_spec.rb +72 -0
  110. data/spec/core/commands/git/show_command_spec.rb +128 -0
  111. data/spec/core/commands/git/snapshot_command_spec.rb +86 -0
  112. data/spec/core/commands/git/status_command_spec.rb +154 -0
  113. data/spec/core/commands/queuing/enqueue_commit_command_spec.rb +34 -0
  114. data/spec/core/commands/queuing/requeue_commit_command_spec.rb +46 -0
  115. data/spec/core/commands/translations/export_command_spec.rb +113 -0
  116. data/spec/core/commands/translations/translation_lookup_command_spec.rb +58 -0
  117. data/spec/core/configurator_spec.rb +47 -0
  118. data/spec/core/error_reporters/buffered_error_reporter_spec.rb +61 -0
  119. data/spec/core/error_reporters/nil_error_reporter_spec.rb +16 -0
  120. data/spec/core/error_reporters/printing_error_reporter_spec.rb +60 -0
  121. data/spec/core/extractor/commit_log_status_spec.rb +216 -0
  122. data/spec/core/extractor/commit_processor_spec.rb +68 -0
  123. data/spec/core/extractor/extractor_config_spec.rb +47 -0
  124. data/spec/core/extractor/extractor_spec.rb +26 -0
  125. data/spec/core/extractor/locale_spec.rb +92 -0
  126. data/spec/core/extractor/phrase/phrase_index_policy_spec.rb +116 -0
  127. data/spec/core/extractor/phrase/phrase_to_hash_spec.rb +18 -0
  128. data/spec/core/extractor/repo_config_spec.rb +147 -0
  129. data/spec/core/extractor/translation/translation_to_hash_spec.rb +25 -0
  130. data/spec/core/git/diff_finder_spec.rb +74 -0
  131. data/spec/core/git/ref_spec.rb +118 -0
  132. data/spec/core/git/repo_spec.rb +216 -0
  133. data/spec/core/path_matcher_factory_spec.rb +139 -0
  134. data/spec/core/resolvers/extractor_id_spec.rb +47 -0
  135. data/spec/core/resolvers/integration_id_spec.rb +47 -0
  136. data/spec/core/resolvers/preprocessor_id_spec.rb +47 -0
  137. data/spec/core/resolvers/serializer_id_spec.rb +47 -0
  138. data/spec/core/snapshots/snapshot_factory_spec.rb +145 -0
  139. data/spec/core/string_utils_spec.rb +19 -0
  140. data/spec/core/translation_status_spec.rb +91 -0
  141. data/spec/core/validators/commit_validator_spec.rb +40 -0
  142. data/spec/core/validators/encoding_validator_spec.rb +30 -0
  143. data/spec/core/validators/locale_validator_spec.rb +31 -0
  144. data/spec/core/validators/repo_validator_spec.rb +30 -0
  145. data/spec/core/validators/serializer_validator_spec.rb +31 -0
  146. data/spec/integrations/integratable_spec.rb +58 -0
  147. data/spec/queuing/commits/commit_conductor_spec.rb +71 -0
  148. data/spec/queuing/commits/commit_job_spec.rb +87 -0
  149. data/spec/queuing/commits/extract_stage_spec.rb +68 -0
  150. data/spec/queuing/commits/fetch_stage_spec.rb +101 -0
  151. data/spec/queuing/commits/finalize_stage_spec.rb +88 -0
  152. data/spec/queuing/commits/push_stage_spec.rb +145 -0
  153. data/spec/queuing/commits/stage_spec.rb +80 -0
  154. data/spec/queuing/job_spec.rb +33 -0
  155. data/spec/queuing/queue_configurator_spec.rb +44 -0
  156. data/spec/spec_helper.rb +90 -0
  157. data/spec/test_helpers/fake_commit_stage.rb +17 -0
  158. metadata +257 -0
@@ -0,0 +1,37 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Logic for handling serializer ids. Serializer ids are strings that refer to
7
+ # a particular serializer class. For example, the id 'yaml/rails' refers to
8
+ # +Rosette::Serializers::YamlSerializer::RailsSerializer+.
9
+ #
10
+ # @example
11
+ # SerializerId.resolve('yaml/rails')
12
+ # # => Rosette::Serializers::YamlSerializer::RailsSerializer
13
+ class SerializerId < Resolver
14
+ class << self
15
+
16
+ # Parses and identifies the class constant for the given serializer id.
17
+ #
18
+ # @param [Class, String] serializer_id When given a class, returns the
19
+ # class. When given a string, parses and identifies the corresponding
20
+ # class constant in +namespace+.
21
+ # @param [Class] namespace The namespace to look in.
22
+ # @return [Class] The identified class constant.
23
+ def resolve(serializer_id, namespace = Rosette::Serializers)
24
+ super
25
+ end
26
+
27
+ private
28
+
29
+ def suffix
30
+ 'Serializer'
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'digest/sha1'
4
+
5
+ module Rosette
6
+ module Core
7
+
8
+ # Takes head snapshots and caches the results. Take a look at
9
+ # +ActiveSupport::Cache+ for a good set of cache stores that conform to the
10
+ # right interface.
11
+ #
12
+ # @see http://api.rubyonrails.org/classes/ActiveSupport/Cache.html
13
+ #
14
+ # @!attribute [r] cache
15
+ # @return [#fetch] the cache store. This can be any object that responds
16
+ # to +#fetch+ (and passes a block).
17
+ class CachedHeadSnapshotFactory < HeadSnapshotFactory
18
+ attr_reader :cache
19
+
20
+ # Creates a new cached head snapshot factory that uses the given cache.
21
+ #
22
+ # @param [#fetch] cache The cache to use.
23
+ def initialize(cache)
24
+ @cache = cache
25
+ end
26
+
27
+ protected
28
+
29
+ def process_ref(rev_walk, ref)
30
+ cache_key = head_snapshot_cache_key(
31
+ repo_config.name,
32
+ repo_config.repo.get_rev_commit(ref, rev_walk).getId.name
33
+ )
34
+
35
+ cache.fetch(cache_key) do
36
+ super
37
+ end
38
+ end
39
+
40
+ def head_snapshot_cache_key(repo_name, commit_id)
41
+ ['head_snapshots', repo_config.name, commit_id].join('/')
42
+ end
43
+
44
+ def head_snapshot_factory
45
+ Rosette::Core::HeadSnapshotFactory
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'digest/sha1'
4
+
5
+ module Rosette
6
+ module Core
7
+
8
+ # Takes snapshots and caches the results. Take a look at
9
+ # +ActiveSupport::Cache+ for a good set of cache stores that conform to the
10
+ # right interface.
11
+ #
12
+ # @see http://api.rubyonrails.org/classes/ActiveSupport/Cache.html
13
+ #
14
+ # @!attribute [r] cache
15
+ # @return [#fetch] the cache store. This can be any object that responds
16
+ # to +#fetch+ (and passes a block).
17
+ class CachedSnapshotFactory
18
+ attr_reader :cache
19
+
20
+ # Creates a new cached snapshot factory that uses the given cache.
21
+ #
22
+ # @param [#fetch] cache The cache to use.
23
+ def initialize(cache)
24
+ @cache = cache
25
+ end
26
+
27
+ # Takes the snapshot.
28
+ #
29
+ # @param [RepoConfig] repo_config The repo config for the repo to take
30
+ # the snapshot for.
31
+ # @param [String] commit_id The commit id to take the snapshot of.
32
+ # @param [Array<String>] paths The list of paths to include in the
33
+ # snapshot. If +paths+ is empty, this method will return a snapshot
34
+ # that contains all paths.
35
+ # @return [Hash<String, String>] The snapshot hash (path to commit id
36
+ # pairs).
37
+ def take_snapshot(repo_config, commit_id, paths = [])
38
+ paths = Array(paths)
39
+ cache_key = snapshot_cache_key(repo_config.name, commit_id, paths)
40
+
41
+ cache.fetch(cache_key) do
42
+ factory = snapshot_factory.new
43
+ .set_repo_config(repo_config)
44
+ .set_start_commit_id(commit_id)
45
+
46
+ factory.set_paths(paths) if paths.size > 0
47
+ factory.take_snapshot
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def snapshot_cache_key(repo_name, commit_id, paths)
54
+ ['snapshots', repo_name, commit_id, path_digest(paths)].join('/')
55
+ end
56
+
57
+ def path_digest(paths)
58
+ Digest::MD5.hexdigest(paths.join)
59
+ end
60
+
61
+ def snapshot_factory
62
+ Rosette::Core::SnapshotFactory
63
+ end
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: UTF-8
2
+
3
+ java_import 'org.eclipse.jgit.revwalk.RevWalk'
4
+ java_import 'org.eclipse.jgit.revwalk.filter.RevFilter'
5
+
6
+ module Rosette
7
+ module Core
8
+
9
+ # Takes a snapshot of all the repository's heads. A "head" snapshot is a
10
+ # key/value map (hash) of git refs (i.e. branch names) to commit ids,
11
+ # where the commit ids are the first non-merge commits for each branch.
12
+ #
13
+ # @example
14
+ # snapshot = HeadSnapshotFactory.new
15
+ # .set_repo_config(config)
16
+ # .take_snapshot
17
+ #
18
+ # @!attribute [r] repo_config
19
+ # @return [RepoConfig] the repo config that contains the repo to take
20
+ # the snapshot for.
21
+ class HeadSnapshotFactory
22
+ attr_reader :repo_config
23
+
24
+ # Sets the repo config that contains the repo to take the snapshot for.
25
+ #
26
+ # @param [RepoConfig] repo_config
27
+ # @return [self]
28
+ def set_repo_config(repo_config)
29
+ @repo_config = repo_config
30
+ self
31
+ end
32
+
33
+ # Takes the snapshot.
34
+ #
35
+ # @return [Hash<String, String>] The head snapshot hash of refs to
36
+ # commit ids.
37
+ def take_snapshot
38
+ rev_walk = RevWalk.new(repo_config.repo.jgit_repo)
39
+ repo_config.repo.all_head_refs.each_with_object({}) do |ref, snapshot|
40
+ snapshot[ref] = process_ref(rev_walk, ref)
41
+ end
42
+ end
43
+
44
+ protected
45
+
46
+ def process_ref(rev_walk, ref)
47
+ rev_walk.reset
48
+ rev_walk.markStart(repo_config.repo.get_rev_commit(ref, rev_walk))
49
+ rev_walk.setRevFilter(RevFilter::NO_MERGES)
50
+
51
+ if rev_commit = rev_walk.next
52
+ rev_commit.getId.name
53
+ end
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: UTF-8
2
+
3
+ java_import 'org.eclipse.jgit.treewalk.filter.TreeFilter'
4
+
5
+ module Rosette
6
+ module Core
7
+
8
+ # A jgit tree filter that filters by the path rules specified in the given
9
+ # {RepoConfig}.
10
+ #
11
+ # @example
12
+ # filter = RepoConfigPathFilter.create(repo_config)
13
+ # factory = Rosette::Core::SnapshotFactory.new
14
+ # .set_repo('my_repo')
15
+ #
16
+ # factory.add_filter(filter)
17
+ # factory.take_snapshot(...)
18
+ #
19
+ # @!attribute [rw] repo_config
20
+ # @return [Array<String>] the configuration to use when filtering paths
21
+ class RepoConfigPathFilter < TreeFilter
22
+ # Creates a new filter with the given repo config.
23
+ #
24
+ # @param [RepoConfig] repo_config The configuration to use when
25
+ # filtering paths
26
+ # @return [FileTypeFilter]
27
+ def self.create(repo_config)
28
+ # Do this because jruby is dumb (i.e. doesn't let you override java
29
+ # constructors)
30
+ new.tap do |obj|
31
+ obj.repo_config = repo_config
32
+ end
33
+ end
34
+
35
+ attr_accessor :repo_config
36
+
37
+ # Overridden. Returns true if the current file matches false otherwise.
38
+ # Generally this method is only called by Jgit internals.
39
+ #
40
+ # @param [Java::OrgEclipseJgitTreewalk::TreeWalk] walker The walker with
41
+ # the current file.
42
+ # @return [Boolean]
43
+ def include(walker)
44
+ if walker.isSubtree
45
+ true
46
+ else
47
+ path = walker.getPathString
48
+
49
+ if repo_config.extractor_configs.size > 0
50
+ repo_config.extractor_configs.any? do |extractor_config|
51
+ extractor_config.matches?(path)
52
+ end
53
+ else
54
+ true
55
+ end
56
+ end
57
+ end
58
+
59
+ # Returns true if this filter should be applied recursively, false otherwise.
60
+ # For this particular filter, always returns true.
61
+ #
62
+ # @return [Boolean]
63
+ def shouldBeRecursive
64
+ true
65
+ end
66
+
67
+ # Clones this filter. For this particular filter, always returns self.
68
+ #
69
+ # @return [self]
70
+ def clone
71
+ self
72
+ end
73
+
74
+ # Returns a string representation of this filter.
75
+ #
76
+ # @return [String]
77
+ def to_s
78
+ "REPO_CONFIG_FILTER"
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,184 @@
1
+ # encoding: UTF-8
2
+
3
+ java_import 'org.eclipse.jgit.revwalk.RevWalk'
4
+ java_import 'org.eclipse.jgit.revwalk.filter.RevFilter'
5
+ java_import 'org.eclipse.jgit.treewalk.EmptyTreeIterator'
6
+ java_import 'org.eclipse.jgit.treewalk.TreeWalk'
7
+ java_import 'org.eclipse.jgit.treewalk.filter.AndTreeFilter'
8
+ java_import 'org.eclipse.jgit.treewalk.filter.PathFilter'
9
+ java_import 'org.eclipse.jgit.treewalk.filter.PathFilterGroup'
10
+ java_import 'org.eclipse.jgit.treewalk.filter.TreeFilter'
11
+
12
+ require 'set'
13
+
14
+ module Rosette
15
+ module Core
16
+
17
+ # Takes snapshots of git repos. A snapshot is a simple key/value map (hash)
18
+ # of paths to commit ids. The commit id is the last time the file changed.
19
+ #
20
+ # @example
21
+ # snapshot = SnapshotFactory.new
22
+ # .set_repo_config(repo_config)
23
+ # .set_start_commit_id('73cd130a42017d794ffa86ef0d255541d518a7b3')
24
+ # .take_snapshot
25
+ #
26
+ # @!attribute [r] repo_config
27
+ # @return [Repo] the +RepoConfig+ object to use when filtering paths, etc.
28
+ # @!attribute [r] start_commit_id
29
+ # @return [String] the git commit id to start at. File changes that
30
+ # occurred more recently than this commit will not be reflected in
31
+ # the snapshot.
32
+ class SnapshotFactory
33
+ attr_reader :repo_config, :start_commit_id, :paths
34
+
35
+ # Creates a new factory.
36
+ def initialize
37
+ reset
38
+ end
39
+
40
+ # Sets the Rosette repo object to use.
41
+ #
42
+ # @param [Repo] repo The Rosette repo object to use.
43
+ # @return [self]
44
+ def set_repo_config(repo_config)
45
+ @repo_config = repo_config
46
+ self
47
+ end
48
+
49
+ # Sets the starting commit id. File changes that occurred more recently
50
+ # than this commit will not be reflected in the snapshot. In other words,
51
+ # this is the commit id to take the snapshot of.
52
+ #
53
+ # @param [String] commit_id The starting commit id.
54
+ # @return [self]
55
+ def set_start_commit_id(commit_id)
56
+ @start_commit_id = commit_id
57
+ self
58
+ end
59
+
60
+ # Set the paths that will be included in the snapshot.
61
+ #
62
+ # @param [Array] paths The paths to include in the snapshot.
63
+ # @return [self]
64
+ def set_paths(paths)
65
+ @paths = paths
66
+ self
67
+ end
68
+
69
+ # Takes the snapshot.
70
+ #
71
+ # @return [Hash<String, String>] The snapshot hash (path to commit id
72
+ # pairs).
73
+ def take_snapshot
74
+ build_hash.tap do
75
+ reset
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def build_hash
82
+ repo = repo_config.repo
83
+ rev_walk = RevWalk.new(repo.jgit_repo)
84
+ rev_commit = repo.get_rev_commit(start_commit_id, rev_walk)
85
+ path_set = (make_path_set(rev_commit) + paths).to_a
86
+ num_replacements = 0
87
+
88
+ tree_filter = if path_set.size > 0
89
+ path_filter = if repo_config && path_set.empty?
90
+ RepoConfigPathFilter.create(repo_config)
91
+ else
92
+ PathFilterGroup.createFromStrings(path_set)
93
+ end
94
+
95
+ AndTreeFilter.create(path_filter, TreeFilter::ANY_DIFF)
96
+ end
97
+
98
+ {}.tap do |path_hash|
99
+ tree_walk = TreeWalk.new(repo.jgit_repo)
100
+ rev_walk.markStart(rev_commit)
101
+
102
+ while cur_commit = rev_walk.next
103
+ cur_commit_id = cur_commit.getId.name
104
+
105
+ tree_walk.reset
106
+ parent_count = cur_commit.getParentCount
107
+
108
+ if parent_count == 0
109
+ tree_walk.addTree(EmptyTreeIterator.new)
110
+ else
111
+ parent_count.times do |i|
112
+ tree_walk.addTree(cur_commit.getParent(i).getTree)
113
+ end
114
+ end
115
+
116
+ tree_walk.addTree(cur_commit.getTree)
117
+ tree_walk.setFilter(tree_filter)
118
+ tree_walk.setRecursive(true)
119
+
120
+ each_file_in(tree_walk) do |walker|
121
+ path = walker.getPathString
122
+
123
+ unless path_hash[path]
124
+ path_hash[path] = cur_commit_id
125
+ num_replacements += 1
126
+ end
127
+ end
128
+
129
+ if num_replacements > path_hash.size
130
+ break
131
+ end
132
+ end
133
+
134
+ rev_walk.dispose
135
+ tree_walk.release
136
+ end
137
+ end
138
+
139
+ def make_path_set(rev_commit)
140
+ path_gatherer = make_path_gatherer(rev_commit)
141
+
142
+ files = each_file_in(path_gatherer).each_with_object(Set.new) do |walker, ret|
143
+ ret << walker.getPathString
144
+ end
145
+
146
+ path_gatherer.release
147
+ files
148
+ end
149
+
150
+ def make_path_gatherer(rev_commit)
151
+ TreeWalk.new(repo_config.repo.jgit_repo).tap do |walker|
152
+ walker.addTree(rev_commit.getTree)
153
+ walker.setRecursive(true)
154
+
155
+ # explicit paths take precedence over repo config ones
156
+ filter = if paths.size > 0
157
+ PathFilterGroup.createFromStrings(paths)
158
+ elsif repo_config
159
+ RepoConfigPathFilter.create(repo_config)
160
+ end
161
+
162
+ walker.setFilter(filter) if filter
163
+ end
164
+ end
165
+
166
+ def reset
167
+ @repo_config = nil
168
+ @start_commit_id = nil
169
+ @paths = []
170
+ end
171
+
172
+ def each_file_in(tree_walk)
173
+ if block_given?
174
+ while tree_walk.next
175
+ yield tree_walk
176
+ end
177
+ else
178
+ to_enum(__method__, tree_walk)
179
+ end
180
+ end
181
+ end
182
+
183
+ end
184
+ end