rjgit 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9e630be01944c941f17a49c0672e3b4e6152d5b
4
+ data.tar.gz: 83a4b49462dcb91f3752f6efd78e3f07365472e5
5
+ SHA512:
6
+ metadata.gz: d993640e4a08b325bda42aef04ccaf2eca55afd5b1ac47d8553398c343db871635a0216f6543da639a1ddb60f373a1c87df7ea928ab4b672f8c6f5937802d965
7
+ data.tar.gz: c75fe41b10fb0b21cd4d48944d981bace59aa130455e3468e92d9426edc0b54a0e0f6f006748cc2add6cc3ddb0829bdacf32669e63b08a95e0ed80a03999ac1b
data/Gemfile CHANGED
@@ -1,11 +1,11 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem "mime-types", "~> 1.15"
4
- gem "rake", "~> 0.9.2.2"
4
+ gem "rake", "~> 10.1.0"
5
5
 
6
6
  gem 'coveralls', require: false
7
7
 
8
8
  group :test do
9
- gem "rspec", "~> 2.0"
9
+ gem "rspec", "2.13.0"
10
10
  gem "simplecov"
11
- end
11
+ end
data/README.md CHANGED
@@ -5,6 +5,7 @@ RJGit
5
5
 
6
6
  [![Build Status](https://travis-ci.org/repotag/rjgit.png)](https://travis-ci.org/repotag/rjgit)
7
7
  [![Coverage Status](https://coveralls.io/repos/repotag/rjgit/badge.png?branch=master)](https://coveralls.io/r/repotag/rjgit)
8
+ [![Gem Version](https://badge.fury.io/rb/rjgit.png)](http://badge.fury.io/rb/rjgit)
8
9
 
9
10
  Authors
10
11
  -------
@@ -37,7 +38,9 @@ $ gem install rjgit
37
38
 
38
39
  Usage
39
40
  -----
40
- RJGit wraps most (if not all) of JGit's core functionality; see below for some examples of what you can do with it. Make sure you have [JRuby](http://jruby.org/) installed.
41
+ RJGit wraps most (if not all) of JGit's core functionality; it has classes for all important Git objects, i.e., Repo, Blob, Tree, Commit, and Tag. It allows parsing and manipulation of these objects in an intuitive manner, either simulating ordinary git usage (with a working directory on disk) or on a lower level, through creating new git objects manually (also works with 'bare' repositories, without a working directory).
42
+
43
+ See below for some examples of what you can do with RJGit. Make sure you have [JRuby](http://jruby.org/) installed.
41
44
 
42
45
  ### Require the gem and include the RJGit module
43
46
 
@@ -56,33 +59,53 @@ repo = Repo.new("repo.git")
56
59
 
57
60
  ```ruby
58
61
  repo = Repo.new("repo.git", :create => true)
59
- repo = Repo.new("repo.git", :create => true, :bare => true) # Create a 'bare' git repo, which stores all git-data under the '.git' directory.
62
+ repo = Repo.new("repo.git", :create => true, :is_bare => true) # Create a 'bare' git repo.
63
+ repo.bare? # Is this a bare repository?
60
64
  ```
61
65
 
62
- ### Getting a list of commits
66
+ ### Getting commits
63
67
  ```ruby
64
68
  repo.commits('master')
65
69
  repo.commits('959329025f67539fb82e76b02782322fad032821')
70
+ commit = repo.commits('master').first # a Commit object; try commit.actor, commit.id, etc.
66
71
  # Similarly for getting tags, branches, trees (directories), and blobs (files).
67
72
  ```
68
73
 
74
+ ### Finding a single object by SHA
75
+ ```ruby
76
+ repo.find('959329025f67539fb82e76b02782322fad032821')
77
+ repo.find('959329025f67539fb82e76b02782322fad032821', :commit) # Find a specific :commit, :blob, :tree, or :tag
78
+ ```
79
+
69
80
  ### Getting tags
70
81
  ```ruby
71
82
  tag = repo.tags['example_tag']
72
83
  tag.id # tag's object id
73
84
  tag.author.name # Etcetera
85
+ some_object = Porcelain.object_for_tag(repo, tag) # Returns the tagged object; e.g. a Commit
86
+ ```
87
+
88
+ ### Blobs and Trees
89
+ ```ruby
90
+ blob = repo.blob("example/file.txt") # Retrieve a file by filepath...
91
+ blob = repo.find("959329025f67539fb82e76b02782322fad032822", :blob) # ...or by SHA
92
+ blob.data # Cat the file; also blob.id, blob.mode, etc.
93
+ tree = repo.tree("example") # Retrieve a tree by filepath...
94
+ tree = repo.find("959329025f67539fb82e76b02782322fad032000", :tree) #...or by SHA
95
+ tree.data # List the tree's contents (blobs and trees). Also tree.id, tree.mode, etc.
96
+ tree.each {|entry| puts entry.inspect} # Loop over the Tree's children (Blobs and Trees)
97
+ tree.trees # An array of the Tree's child Trees
98
+ tree.blobs # An array of the Tree's child Blobs
99
+ Porcelain::ls_tree(repo, repo.tree("example"), :print => true, :recursive => true, :branch => 'mybranch') # Outputs the Tree's contents to $stdout. Faster for recursive listing than Tree#each. Passing nil as the second argument lists the entire repository. Branch defaults to HEAD.
74
100
  ```
75
101
 
76
- ### Getting a repository's contents
102
+ ### Creating blobs and trees from scratch
77
103
  ```ruby
78
- repo.blob("example/file.txt") # Retrieve a file by filepath
79
- repo.blob("example/file.txt").data # Cat the file
80
- repo.tree("example") # Retrieve a tree by filepath
81
- repo.tree("example").data # List the tree's contents (blobs and trees)
82
- Porcelain::ls_tree(repo, repo.tree("example"), :print => true, :recursive => true, :branch => 'mybranch') # Outputs a file list to $stdout. Passing nil as the second argument lists the entire repository. Branch defaults to HEAD.
104
+ blob = Blob.new_from_string(repo, "Contents of the new blob.") # Inserts the blob into the repository, returns an RJGit::Blob
105
+ tree = Tree.new_from_hashmap(repo, {"newblob" => "contents", "newtree" => { "otherblob" => "this blob is contained in the tree 'newtree'" } } ) # Constructs the tree and its children based on the hashmap and inserts it into the repository, returning an RJGit::Tree. Tree.new_from_hashmap takes an RJGit::Tree as an optional third argument, in which case the new tree will consist of the children of that Tree *plus* the contents of the hashmap.
83
106
  ```
84
107
 
85
- ### Manipulating repositories
108
+ ### Committing and adding branches to repositories, 'porcelain' style (only works with non-bare repos)
86
109
  ```ruby
87
110
  repo.create_branch('new_branch') # Similarly for deleting, renaming
88
111
  repo.checkout('new_branch')
@@ -90,6 +113,14 @@ repo.add('new_file.txt') # Similarly for removing
90
113
  repo.commit('My message')
91
114
  ```
92
115
 
116
+ ### Committing and adding branches to repositories, 'plumbing' style (also works with bare repos)
117
+ ```ruby
118
+ repo = repo.new("repo.git")
119
+ tree = Tree.new_from_hashmap(repo, {"newblob" => "contents"}, repo.head.tree ) # As above, use the current head commit's tree as a starting point and add "newblob"
120
+ actor = RJGit::Actor.new("test", "test@repotag.org")
121
+ commit = Commit.new_with_tree(repo, tree, "My commit message", actor) # Create a new commit with tree as base tree
122
+ ```
123
+
93
124
  ### And more...
94
125
  ```ruby
95
126
  pack = RJGitReceivePack.new(repo) # Implement the smart-http protocol with RJGitReceivePack and RJGitUploadPack
data/lib/actor.rb CHANGED
@@ -9,15 +9,18 @@ module RJGit
9
9
 
10
10
  RJGit.delegate_to(PersonIdent, :@person_ident)
11
11
 
12
- def self.new_from_name_and_email(name, email)
13
- return self.new(PersonIdent.new(name, email))
14
- end
15
12
  alias_method :to_s, :name
16
-
17
- def initialize(person_ident)
18
- @name = person_ident.get_name
19
- @email = person_ident.get_email_address
20
- @person_ident = person_ident
13
+
14
+ def self.new_from_person_ident(person_ident)
15
+ name = person_ident.get_name
16
+ email = person_ident.get_email_address
17
+ return self.new(name, email)
18
+ end
19
+
20
+ def initialize(name, email)
21
+ @name = name
22
+ @email = email
23
+ @person_ident = PersonIdent.new(name, email)
21
24
  end
22
25
 
23
26
  # Create an Actor from a string.
@@ -28,7 +31,7 @@ module RJGit
28
31
  def self.from_string(str)
29
32
  if str =~ /<.+>/
30
33
  m, name, email = *str.match(/(.*) <(.+?)>/)
31
- return self.new_from_name_and_email(name, email)
34
+ return self.new(name, email)
32
35
  end
33
36
  end
34
37
 
data/lib/blob.rb CHANGED
@@ -7,11 +7,11 @@ module RJGit
7
7
  attr_reader :id, :mode, :name, :path, :jblob
8
8
  RJGit.delegate_to(RevBlob, :@jblob)
9
9
 
10
- def initialize(jrepo, path, mode, jblob)
11
- @jrepo = jrepo
10
+ def initialize(repository, mode, path, jblob)
11
+ @jrepo = RJGit.repository_type(repository)
12
12
  @jblob = jblob
13
13
  @path = path
14
- @name = File.basename(path)
14
+ @name = @path ? File.basename(@path) : nil
15
15
  @mode = mode
16
16
  @id = ObjectId.toString(jblob.get_id)
17
17
  end
@@ -36,7 +36,11 @@ module RJGit
36
36
  def data
37
37
  @data ||= RJGit::Porcelain.cat_file(@jrepo, @jblob)
38
38
  end
39
-
39
+
40
+ def is_symlink?
41
+ @mode == SYMLINK_TYPE
42
+ end
43
+
40
44
  # The mime type of this file (based on the filename)
41
45
  # Returns String
42
46
  def mime_type
@@ -48,10 +52,17 @@ module RJGit
48
52
  guesses.first ? guesses.first.simplified : DEFAULT_MIME_TYPE
49
53
  end
50
54
 
55
+ def self.new_from_string(repository, contents)
56
+ repository = RJGit.repository_type(repository)
57
+ blob_id = RJGit::Plumbing::TreeBuilder.new(repository).write_blob(contents, true)
58
+ walk = RevWalk.new(repository)
59
+ Blob.new(repository, FileMode::REGULAR_FILE, nil, walk.lookup_blob(blob_id))
60
+ end
61
+
51
62
  # Finds a particular Blob in repository matching file_path
52
- def self.find_blob(repository, file_path, branch=Constants::HEAD)
63
+ def self.find_blob(repository, file_path, revstring=Constants::HEAD)
53
64
  jrepo = RJGit.repository_type(repository)
54
- last_commit_hash = jrepo.resolve(branch)
65
+ last_commit_hash = jrepo.resolve(revstring)
55
66
  return nil if last_commit_hash.nil?
56
67
 
57
68
  walk = RevWalk.new(jrepo)
@@ -64,8 +75,8 @@ module RJGit
64
75
  if treewalk.next
65
76
  jblob = walk.lookup_blob(treewalk.objectId(0))
66
77
  if jblob
67
- mode = RJGit.get_file_mode(jrepo, file_path, jtree)
68
- Blob.new(jrepo, file_path, mode, jblob)
78
+ mode = RJGit.get_file_mode_with_path(jrepo, file_path, jtree)
79
+ Blob.new(jrepo, mode, file_path, jblob)
69
80
  end
70
81
  else
71
82
  nil
data/lib/commit.rb CHANGED
@@ -14,23 +14,48 @@ module RJGit
14
14
  attr_reader :message
15
15
  attr_reader :short_message
16
16
  attr_reader :jcommit
17
- attr_reader :count
17
+ attr_reader :parent_count
18
18
 
19
19
  RJGit.delegate_to(RevCommit, :@jcommit)
20
20
 
21
- def initialize(commit)
21
+ def initialize(repository, commit)
22
+ @jrepo = RJGit.repository_type(repository)
22
23
  @jcommit = commit
23
24
  @id = ObjectId.to_string(commit.get_id)
24
- @actor = Actor.new(@jcommit.get_author_ident)
25
- @committer = Actor.new(@jcommit.get_committer_ident)
25
+ @actor = Actor.new_from_person_ident(@jcommit.get_author_ident)
26
+ @committer = Actor.new_from_person_ident(@jcommit.get_committer_ident)
26
27
  @committed_date = Time.at(@jcommit.commit_time)
27
28
  @message = @jcommit.get_full_message
28
29
  @short_message = @jcommit.get_short_message
29
- @count = @jcommit.get_parent_count
30
+ @parent_count = @jcommit.get_parent_count
31
+ end
32
+
33
+ def tree
34
+ @tree ||= Tree.new(@jrepo, FileMode::TREE, nil, @jcommit.get_tree)
30
35
  end
31
36
 
32
37
  def parents
33
- @parents ||= @jcommit.get_parents.map{|parent| Commit.new(parent) }
38
+ @parents ||= @jcommit.get_parents.map {|parent| Commit.new(@jrepo, parent)}
39
+ end
40
+
41
+ # Pass an empty array for parents if the commit should have no parents
42
+ def self.new_with_tree(repository, tree, message, actor, parents = nil)
43
+ repository = RJGit.repository_type(repository)
44
+ parents = parents ? parents : repository.resolve("refs/heads/#{Constants::MASTER}")
45
+ new_commit = RJGit::Plumbing::Index.new(repository).do_commit(message, actor, parents, tree)
46
+ Commit.new(repository, RevWalk.new(repository).parseCommit(new_commit))
47
+ end
48
+
49
+ def self.find_head(repository)
50
+ repository = RJGit.repository_type(repository)
51
+ return nil if repository.nil?
52
+ begin
53
+ walk = RevWalk.new(repository)
54
+ objhead = repository.resolve(Constants::HEAD)
55
+ return Commit.new(repository, walk.parseCommit(objhead))
56
+ rescue NativeException => e
57
+ return nil
58
+ end
34
59
  end
35
60
 
36
61
  def self.find_all(repository, ref, options)
@@ -41,7 +66,7 @@ module RJGit
41
66
  objhead = repository.resolve(ref)
42
67
  root = walk.parse_commit(objhead)
43
68
  walk.mark_start(root)
44
- commits = walk.map { |commit| Commit.new(commit) }
69
+ commits = walk.map { |commit| Commit.new(repository, commit) }
45
70
  return commits.first(options[:limit])
46
71
  rescue NativeException => e
47
72
  return Array.new
data/lib/config.rb CHANGED
@@ -42,7 +42,7 @@ module RJGit
42
42
  end
43
43
  settings[name] = value
44
44
  end
45
- settings
45
+ settings.empty? ? nil : settings
46
46
  end
47
47
 
48
48
  def is_num?(str)
data/lib/git.rb CHANGED
@@ -27,7 +27,7 @@ module RJGit
27
27
  logs = @jgit.log
28
28
  commits = Array.new
29
29
  logs.call.each do |jcommit|
30
- commits << Commit.new(jcommit)
30
+ commits << Commit.new(jrepo, jcommit)
31
31
  end
32
32
  commits
33
33
  end
@@ -42,7 +42,7 @@ module RJGit
42
42
  end
43
43
 
44
44
  def commit(message)
45
- Commit.new(@jgit.commit.set_message(message).call)
45
+ Commit.new(jrepo, @jgit.commit.set_message(message).call)
46
46
  end
47
47
 
48
48
  def clone(remote, local, options = {})
@@ -53,7 +53,7 @@ module RJGit
53
53
  clone_command = Git.clone_repository
54
54
  clone_command.setURI(remote)
55
55
  clone_command.set_directory(java.io.File.new(local))
56
- clone_command.set_bare(true) if options[:bare]
56
+ clone_command.set_bare(true) if options[:is_bare]
57
57
  if options[:branch]
58
58
  if options[:branch] == :all
59
59
  clone_command.set_clone_all_branches(true)
@@ -92,7 +92,7 @@ module RJGit
92
92
  tag_command.set_name(name)
93
93
  tag_command.set_force_update(force)
94
94
  tag_command.set_message(message)
95
- tag_command.set_object_id(commit_or_revision) if commit_or_revision
95
+ tag_command.set_object_id(RJGit.commit_type(commit_or_revision)) if commit_or_revision
96
96
  if actor
97
97
  actor = RJGit.actor_type(actor)
98
98
  tag_command.set_tagger(actor)
@@ -182,7 +182,7 @@ module RJGit
182
182
  commits.each do |commit|
183
183
  revert_command.include commit.jcommit
184
184
  end
185
- Commit.new(revert_command.call)
185
+ Commit.new(jrepo, revert_command.call)
186
186
  end
187
187
 
188
188
  def status
data/lib/repo.rb CHANGED
@@ -49,13 +49,13 @@ module RJGit
49
49
  # If the repo path is new
50
50
  unless File.exists?(epath)
51
51
  # take user setting if defined
52
- bare = !! options[:bare] unless options[:bare].nil?
52
+ bare = !! options[:is_bare] unless options[:is_bare].nil?
53
53
  # If the repo path exists
54
54
  else
55
55
  # scan the directory for a .git directory
56
56
  bare = File.exists?(gitpath) ? false : true
57
57
  # but allow overriding user setting
58
- bare = !! options[:bare] unless options[:bare].nil?
58
+ bare = !! options[:is_bare] unless options[:is_bare].nil?
59
59
  end
60
60
 
61
61
  @path = bare ? epath : gitpath
@@ -69,8 +69,9 @@ module RJGit
69
69
  def bare?
70
70
  @jrepo.is_bare
71
71
  end
72
+ alias_method :bare, :bare?
72
73
 
73
- def self.create(path, options = {:bare => false})
74
+ def self.create(path, options = {:is_bare => false})
74
75
  options[:create] = true
75
76
  Repo.new(path, options)
76
77
  end
@@ -79,11 +80,20 @@ module RJGit
79
80
  @jrepo.create(self.bare?)
80
81
  end
81
82
 
83
+ def self.new_from_jgit_repo(jrepo)
84
+ path = File.dirname(jrepo.get_directory.get_path)
85
+ Repo.new(path, {:is_bare => jrepo.is_bare})
86
+ end
87
+
82
88
  def commits(ref="master", limit=100)
83
89
  options = { :limit => limit }
84
90
  Commit.find_all(@jrepo, ref, options)
85
91
  end
86
92
 
93
+ def head
94
+ Commit.find_head(@jrepo)
95
+ end
96
+
87
97
  def valid?
88
98
  @jrepo.get_object_database.exists
89
99
  end
@@ -152,15 +162,58 @@ module RJGit
152
162
  def clean(options = {})
153
163
  @git.clean(options)
154
164
  end
165
+
166
+ def find(sha, type = :any)
167
+ begin
168
+ oi = ObjectId.from_string(sha)
169
+ walk = RevWalk.new(@jrepo)
170
+ rev_object = case type
171
+ when :any
172
+ walk.parse_any(oi)
173
+ when :tree
174
+ walk.parse_tree(oi)
175
+ when :blob
176
+ walk.parse_any(oi)
177
+ when :tag
178
+ walk.parse_tag(oi)
179
+ when :commit
180
+ walk.parse_commit(oi)
181
+ else nil
182
+ end
183
+ rescue Java::OrgEclipseJgitErrors::MissingObjectException, Java::JavaLang::IllegalArgumentException, Java::JavaLang::NullPointerException
184
+ return nil
185
+ end
186
+ return nil if rev_object.nil?
187
+ object_type = (type == :any || type == :blob) ? RJGit.sym_for_type(rev_object.get_type) : type
188
+ return nil if type == :blob && object_type != :blob # Blobs need to be found with parse_any, so make sure that the result of this is actually a blob.
189
+ return case object_type
190
+ when :tree
191
+ Tree.new(@jrepo, nil, nil, rev_object)
192
+ when :blob
193
+ mode = RJGit.get_file_mode(@jrepo, rev_object)
194
+ Blob.new(@jrepo, mode, nil, rev_object)
195
+ when :tag
196
+ Tag.new(rev_object)
197
+ when :commit
198
+ Commit.new(jrepo, rev_object)
199
+ end
200
+ end
155
201
 
156
202
  # Convenience method to retrieve a Blob by name
157
- def blob(file_path)
158
- Blob.find_blob(@jrepo, file_path)
203
+ def blob(file_path, revstring=Constants::HEAD)
204
+ Blob.find_blob(@jrepo, file_path, revstring)
159
205
  end
160
206
 
161
207
  # Convenience method to retrieve a Tree by name
162
- def tree(file_path)
163
- Tree.find_tree(@jrepo, file_path)
208
+ def tree(file_path, revstring=Constants::HEAD)
209
+ Tree.find_tree(@jrepo, file_path, revstring)
210
+ end
211
+
212
+ def update_ref(commit, force = false, ref = "refs/heads/#{Constants::MASTER}")
213
+ ref_updater = @jrepo.updateRef(ref)
214
+ ref_updater.setNewObjectId(RJGit.commit_type(commit))
215
+ msg = force ? :update : :forceUpdate
216
+ ref_updater.send(msg).to_string
164
217
  end
165
218
 
166
219
  # Update the info files required for fetching files over the dump-HTTP protocol
data/lib/rjgit.rb CHANGED
@@ -25,7 +25,7 @@ module RJGit
25
25
 
26
26
  import 'org.eclipse.jgit.lib.ObjectId'
27
27
 
28
- class Porcelain
28
+ module Porcelain
29
29
 
30
30
  import 'org.eclipse.jgit.api.AddCommand'
31
31
  import 'org.eclipse.jgit.api.CommitCommand'
@@ -42,9 +42,23 @@ module RJGit
42
42
  repository.commit(message)
43
43
  end
44
44
 
45
+ def self.object_for_tag(repository, tag)
46
+ repository.find(tag.object.name, RJGit.sym_for_type(tag.object_type))
47
+ end
48
+
45
49
  # http://dev.eclipse.org/mhonarc/lists/jgit-dev/msg00558.html
46
- def self.cat_file(repository, object)
47
- bytes = repository.open(object.id).get_bytes
50
+ def self.cat_file(repository, blob)
51
+ jrepo = RJGit.repository_type(repository)
52
+ jblob = RJGit.blob_type(blob)
53
+ # Try to resolve symlinks; return nil otherwise
54
+ mode = RJGit.get_file_mode(jrepo, jblob)
55
+ if mode == SYMLINK_TYPE
56
+ symlink_source = jrepo.open(jblob.id).get_bytes.to_a.pack('c*').force_encoding('UTF-8')
57
+ blob = Blob.find_blob(jrepo, symlink_source)
58
+ return nil if blob.nil?
59
+ jblob = blob.jblob
60
+ end
61
+ bytes = jrepo.open(jblob.id).get_bytes
48
62
  return bytes.to_a.pack('c*').force_encoding('UTF-8')
49
63
  end
50
64
 
@@ -75,7 +89,7 @@ module RJGit
75
89
  entries << entry
76
90
  end
77
91
  options[:io].puts RJGit.stringify(entries) if options[:print]
78
- entries
92
+ return entries
79
93
  end
80
94
 
81
95
  def self.blame(repository, file_path, options={})
@@ -90,9 +104,9 @@ module RJGit
90
104
  blame = []
91
105
  for index in (0..content.size - 1) do
92
106
  blameline = {}
93
- blameline[:actor] = Actor.new(result.get_source_author(index))
107
+ blameline[:actor] = Actor.new_from_person_ident(result.get_source_author(index))
94
108
  blameline[:line] = result.get_source_line(index)
95
- blameline[:commit] = Commit.new(result.get_source_commit(index))
109
+ blameline[:commit] = Commit.new(repository, result.get_source_commit(index))
96
110
  blameline[:line] = content.get_string(index)
97
111
  blame << blameline
98
112
  end
@@ -112,7 +126,180 @@ module RJGit
112
126
  diff_entries = diff_command.call
113
127
  diff_entries = diff_entries.to_array.to_ary
114
128
  diff_entries = RJGit.convert_diff_entries(diff_entries)
115
- diff_entries
129
+ return diff_entries
130
+ end
131
+
132
+ end
133
+
134
+ module Plumbing
135
+ import org.eclipse.jgit.lib.Constants
136
+
137
+ class TreeBuilder
138
+ import org.eclipse.jgit.lib.FileMode
139
+ import org.eclipse.jgit.lib.TreeFormatter
140
+
141
+
142
+ attr_accessor :treemap
143
+ attr_reader :log
144
+
145
+ def initialize(repository)
146
+ @jrepo = RJGit.repository_type(repository)
147
+ @treemap = {}
148
+ init_log
149
+ end
150
+
151
+ def object_inserter
152
+ @jrepo.newObjectInserter
153
+ end
154
+
155
+ def init_log
156
+ @log = {:deleted => [], :added => [] }
157
+ end
158
+
159
+ def only_contains_deletions(hashmap)
160
+ hashmap.each do |key, value|
161
+ if value.is_a?(Hash) then
162
+ return false unless only_contains_deletions(value)
163
+ elsif value.is_a?(String)
164
+ return false
165
+ end
166
+ end
167
+ true
168
+ end
169
+
170
+ def build_tree(start_tree, treemap = nil, flush = false)
171
+ existing_trees = {}
172
+ formatter = TreeFormatter.new
173
+ treemap ||= self.treemap
174
+
175
+ if start_tree then
176
+ treewalk = TreeWalk.new(@jrepo)
177
+ treewalk.add_tree(start_tree)
178
+ while treewalk.next
179
+ filename = treewalk.get_name_string
180
+ if treemap.keys.include?(filename) then
181
+ kind = treewalk.isSubtree ? :tree : :blob
182
+ if treemap[filename] == false then
183
+ @log[:deleted] << [kind, filename, treewalk.get_object_id(0)]
184
+ else
185
+ existing_trees[filename] = treewalk.get_object_id(0) if kind == :tree
186
+ end
187
+ else
188
+ mode = treewalk.isSubtree ? FileMode::TREE : FileMode::REGULAR_FILE
189
+ formatter.append(filename.to_java_string, treewalk.get_file_mode(0), treewalk.get_object_id(0))
190
+ end
191
+ end
192
+ end
193
+
194
+ treemap.each do |object_name, data|
195
+ case data
196
+ when String
197
+ blobid = write_blob(data)
198
+ formatter.append(object_name.to_java_string, FileMode::REGULAR_FILE, blobid)
199
+ @log[:added] << [:blob, object_name, blobid]
200
+ when Hash
201
+ next_tree = build_tree(existing_trees[object_name], data)
202
+ formatter.append(object_name.to_java_string, FileMode::TREE, next_tree)
203
+ @log[:added] << [:tree, object_name, next_tree] unless only_contains_deletions(data)
204
+ end
205
+ end
206
+
207
+ result = object_inserter.insert(formatter)
208
+ end
209
+
210
+ def write_blob(contents, flush = false)
211
+ blobid = object_inserter.insert(Constants::OBJ_BLOB, contents.to_java_bytes)
212
+ blobid
213
+ end
214
+
215
+ end
216
+
217
+ class Index
218
+ import org.eclipse.jgit.lib.CommitBuilder
219
+
220
+ attr_accessor :treemap, :current_tree
221
+ attr_reader :jrepo
222
+
223
+ def initialize(repository, branch = nil)
224
+ @treemap = {}
225
+ @jrepo = RJGit.repository_type(repository)
226
+ @treebuilder = TreeBuilder.new(@jrepo)
227
+ end
228
+
229
+ def add(path, data)
230
+ path = path[1..-1] if path[0] == '/'
231
+ path = path.split('/')
232
+ filename = path.pop
233
+
234
+ current = self.treemap
235
+
236
+ path.each do |dir|
237
+ current[dir] ||= {}
238
+ node = current[dir]
239
+ current = node
240
+ end
241
+
242
+ current[filename] = data
243
+ @treemap
244
+ end
245
+
246
+ def delete(path)
247
+ path = path[1..-1] if path[0] == '/'
248
+ path = path.split('/')
249
+ last = path.pop
250
+
251
+ current = self.treemap
252
+
253
+ path.each do |dir|
254
+ current[dir] ||= {}
255
+ node = current[dir]
256
+ current = node
257
+ end
258
+
259
+ current[last] = false
260
+ @treemap
261
+ end
262
+
263
+ def do_commit(message, author, parents, new_tree)
264
+ commit_builder = CommitBuilder.new
265
+ person = author.person_ident
266
+ commit_builder.setCommitter(person)
267
+ commit_builder.setAuthor(person)
268
+ commit_builder.setMessage(message)
269
+ commit_builder.setTreeId(RJGit.tree_type(new_tree))
270
+ if parents.is_a?(Array) then
271
+ parents.each {|parent| commit_builder.addParentId(RJGit.commit_type(parent)) }
272
+ elsif parents
273
+ commit_builder.addParentId(RJGit.commit_type(parents))
274
+ end
275
+ @treebuilder.object_inserter.insert(commit_builder)
276
+ end
277
+
278
+ def commit(message, author, parents = nil, ref = "refs/heads/#{Constants::MASTER}")
279
+ @current_tree = @current_tree ? RJGit.tree_type(@current_tree) : @jrepo.resolve("refs/heads/#{Constants::MASTER}^{tree}")
280
+ @treebuilder.treemap = @treemap
281
+ new_tree = @treebuilder.build_tree(@current_tree)
282
+ return false if @current_tree && new_tree.name == @current_tree.name
283
+
284
+ parents = parents ? parents : @jrepo.resolve(ref+"^{commit}")
285
+ new_head = do_commit(message, author, parents, new_tree)
286
+
287
+ # Point ref to the newest commit
288
+ ru = @jrepo.updateRef(ref)
289
+ ru.setNewObjectId(new_head)
290
+ res = ru.forceUpdate.to_string
291
+
292
+ @current_tree = new_tree
293
+ @treemap = {}
294
+ log = @treebuilder.log
295
+ @treebuilder.init_log
296
+ return res, log
297
+ end
298
+
299
+ def self.successful?(result)
300
+ ["NEW", "FAST_FORWARD"].include?(result)
301
+ end
302
+
116
303
  end
117
304
 
118
305
  end
data/lib/rjgit_helpers.rb CHANGED
@@ -16,11 +16,29 @@ module RJGit
16
16
  def_delegators delegate_name, *java_methods
17
17
  end
18
18
 
19
- def self.get_file_mode(repository, path, jtree)
20
- treewalk = TreeWalk.forPath(repository, path, jtree)
19
+ def self.get_file_mode_with_path(jrepo, path, jtree)
20
+ treewalk = TreeWalk.forPath(jrepo, path, jtree)
21
21
  return treewalk.get_file_mode(0).get_bits
22
22
  end
23
23
 
24
+ def self.get_file_mode(jrepo, jblob, revstring=Constants::HEAD)
25
+ last_commit_hash = jrepo.resolve(revstring)
26
+ return nil if last_commit_hash.nil?
27
+ walk = RevWalk.new(jrepo)
28
+ jcommit = walk.parse_commit(last_commit_hash)
29
+ treewalk = TreeWalk.new(jrepo)
30
+ jtree = jcommit.get_tree
31
+ treewalk.add_tree(jtree)
32
+ treewalk.set_recursive(true)
33
+ while treewalk.next
34
+ jblob_lookup = walk.lookup_blob(treewalk.objectId(0))
35
+ if jblob_lookup.get_name == jblob.get_name
36
+ mode = treewalk.get_file_mode(0).get_bits
37
+ return mode
38
+ end
39
+ end
40
+ end
41
+
24
42
  def self.stringify(entries)
25
43
  str = ""
26
44
  entries.each do |entry|
@@ -49,6 +67,18 @@ module RJGit
49
67
  entry
50
68
  end
51
69
 
70
+ def self.sym_for_type(type)
71
+ result = case type
72
+ when Constants::OBJ_BLOB
73
+ :blob
74
+ when Constants::OBJ_TREE
75
+ :tree
76
+ when Constants::OBJ_COMMIT
77
+ :commit
78
+ when Constants::OBJ_TAG
79
+ :tag
80
+ end
81
+ end
52
82
 
53
83
  def self.repository_type(repository)
54
84
  repo = case repository
@@ -70,6 +100,23 @@ module RJGit
70
100
  treeobj = case tree
71
101
  when Tree then tree.jtree
72
102
  when org.eclipse.jgit.revwalk.RevTree then tree
103
+ when org.eclipse.jgit.lib.ObjectId then tree
104
+ else nil
105
+ end
106
+ end
107
+
108
+ def self.blob_type(blob)
109
+ blobobj = case blob
110
+ when Blob then blob.jblob
111
+ when org.eclipse.jgit.revwalk.RevBlob then blob
112
+ else nil
113
+ end
114
+ end
115
+
116
+ def self.commit_type(commit)
117
+ commitobj = case commit
118
+ when Commit then commit.jcommit
119
+ when org.eclipse.jgit.lib.ObjectId then commit
73
120
  else nil
74
121
  end
75
122
  end
data/lib/tag.rb CHANGED
@@ -22,7 +22,7 @@ module RJGit
22
22
  end
23
23
 
24
24
  def actor
25
- @actor ||= Actor.new(@jtag.get_tagger_ident)
25
+ @actor ||= Actor.new_from_person_ident(@jtag.get_tagger_ident)
26
26
  end
27
27
 
28
28
  def name
@@ -33,6 +33,13 @@ module RJGit
33
33
  @type ||= @jtag.get_type
34
34
  end
35
35
 
36
+ def object
37
+ @object ||= @jtag.get_object
38
+ end
39
+
40
+ def object_type
41
+ @object_type ||= object.get_type
42
+ end
36
43
 
37
44
  end
38
45
  end
data/lib/tree.rb CHANGED
@@ -7,26 +7,70 @@ module RJGit
7
7
 
8
8
  attr_reader :contents, :id, :mode, :name, :repo, :jtree
9
9
  RJGit.delegate_to(RevTree, :@jtree)
10
+ include Enumerable
10
11
 
11
12
  def initialize(repository, mode, path, jtree)
12
- @repo = repository
13
+ @jrepo = RJGit.repository_type(repository)
13
14
  @mode = mode
14
15
  @path = path
15
- @name = File.basename(path)
16
+ @name = @path ? File.basename(path) : nil
16
17
  @jtree = jtree
17
18
  @id = ObjectId.to_string(jtree.get_id)
18
19
  end
19
20
 
20
21
  def data
22
+ return @contents if @contents
21
23
  strio = StringIO.new
22
- RJGit::Porcelain.ls_tree(@repo, @jtree, options={:print => true, :io => strio})
23
- strio.string
24
+ RJGit::Porcelain.ls_tree(@jrepo, @jtree, options={:print => true, :io => strio})
25
+ @contents = strio.string
24
26
  end
25
27
 
26
- def self.find_tree(repository, file_path, branch=Constants::HEAD)
28
+ def contents_array
29
+ return @contents_ary if @contents_ary
30
+ results = []
31
+ RJGit::Porcelain.ls_tree(@jrepo, @jtree).each do |item|
32
+ walk = RevWalk.new(@jrepo)
33
+ results << Tree.new(@jrepo, item[:mode], item[:path], walk.lookup_tree(ObjectId.from_string(item[:id]))) if item[:type] == 'tree'
34
+ results << Blob.new(@jrepo, item[:mode], item[:path], walk.lookup_blob(ObjectId.from_string(item[:id]))) if item[:type] == 'blob'
35
+ end
36
+ @contents_ary = results
37
+ end
38
+
39
+ def each(&block)
40
+ contents_array.each(&block)
41
+ end
42
+
43
+ def blobs
44
+ contents_array.select {|x| x.is_a?(Blob)}
45
+ end
46
+
47
+ def trees
48
+ contents_array.select {|x| x.is_a?(Tree)}
49
+ end
50
+
51
+ # From Grit
52
+ def /(file)
53
+ if file =~ /\//
54
+ file.split("/").inject(self) { |acc, x| acc/x } rescue nil
55
+ else
56
+ self.contents_array.find { |c| c.name == file }
57
+ end
58
+ end
59
+
60
+ def self.new_from_hashmap(repository, hashmap, base_tree = nil)
61
+ jrepo = RJGit.repository_type(repository)
62
+ tree_builder = Plumbing::TreeBuilder.new(jrepo)
63
+ base_tree = RJGit.tree_type(base_tree)
64
+ new_tree = tree_builder.build_tree(base_tree, hashmap, true)
65
+ walk = RevWalk.new(jrepo)
66
+ new_tree = walk.lookup_tree(new_tree)
67
+ Tree.new(jrepo, FileMode::TREE, nil, new_tree)
68
+ end
69
+
70
+ def self.find_tree(repository, file_path, revstring=Constants::HEAD)
27
71
  jrepo = RJGit.repository_type(repository)
28
72
  return nil if jrepo.nil?
29
- last_commit_hash = jrepo.resolve(branch)
73
+ last_commit_hash = jrepo.resolve(revstring)
30
74
  return nil if last_commit_hash.nil?
31
75
 
32
76
  walk = RevWalk.new(jrepo)
@@ -38,7 +82,7 @@ module RJGit
38
82
  if treewalk.next
39
83
  jsubtree = walk.lookup_tree(treewalk.object_id(0))
40
84
  if jsubtree
41
- mode = RJGit.get_file_mode(jrepo, file_path, jtree)
85
+ mode = RJGit.get_file_mode_with_path(jrepo, file_path, jtree)
42
86
  Tree.new(jrepo, mode, file_path, jsubtree)
43
87
  end
44
88
  else
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RJGit
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rjgit
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.2.0
4
+ version: 0.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Maarten Engelen
@@ -13,7 +12,7 @@ authors:
13
12
  autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
- date: 2013-07-18 00:00:00.000000000 Z
15
+ date: 2013-12-08 00:00:00.000000000 Z
17
16
  dependencies:
18
17
  - !ruby/object:Gem::Dependency
19
18
  name: mime-types
@@ -22,13 +21,11 @@ dependencies:
22
21
  - - ~>
23
22
  - !ruby/object:Gem::Version
24
23
  version: '1.15'
25
- none: false
26
24
  requirement: !ruby/object:Gem::Requirement
27
25
  requirements:
28
26
  - - ~>
29
27
  - !ruby/object:Gem::Version
30
28
  version: '1.15'
31
- none: false
32
29
  prerelease: false
33
30
  type: :runtime
34
31
  description: JRuby wrapper around the JGit library for manipulating git repositories in code.
@@ -55,11 +52,12 @@ files:
55
52
  - LICENSE
56
53
  - Gemfile
57
54
  - lib/java/jars/jsch-0.1.49.jar
58
- - lib/java/jars/org.eclipse.jgit-3.0.0.201306101825-r.jar
55
+ - lib/java/jars/org.eclipse.jgit-3.1.0.201310021548-r.jar
59
56
  homepage: https://github.com/repotag/rjgit
60
57
  licenses:
61
58
  - Modified BSD
62
59
  - EPL
60
+ metadata: {}
63
61
  post_install_message:
64
62
  rdoc_options:
65
63
  - --charset=UTF-8
@@ -69,21 +67,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
67
  requirements:
70
68
  - - '>='
71
69
  - !ruby/object:Gem::Version
72
- segments:
73
- - 0
74
- hash: 2
75
70
  version: '0'
76
- none: false
77
71
  required_rubygems_version: !ruby/object:Gem::Requirement
78
72
  requirements:
79
73
  - - '>='
80
74
  - !ruby/object:Gem::Version
81
75
  version: '0'
82
- none: false
83
76
  requirements: []
84
77
  rubyforge_project:
85
- rubygems_version: 1.8.24
78
+ rubygems_version: 2.1.9
86
79
  signing_key:
87
- specification_version: 3
80
+ specification_version: 4
88
81
  summary: JRuby wrapper around the JGit library.
89
82
  test_files: []