Class: Gitdocs::Repository
- Inherits:
-
Object
- Object
- Gitdocs::Repository
- Defined in:
- lib/gitdocs/repository.rb
Overview
If a repository is invalid then query methods will return nil, and command methods will raise exceptions.
Wrapper for accessing the shared git repositories. Rugged or Grit will be used, in that order of preference, depending upon the features which are available with each option.
Defined Under Namespace
Classes: Path
Instance Attribute Summary collapse
-
#invalid_reason ⇒ Object
readonly
Returns the value of attribute invalid_reason.
Class Method Summary collapse
-
.clone(path, remote) ⇒ Gitdocs::Repository
Clone a repository, and create the destination path if necessary.
Instance Method Summary collapse
-
#author_count(last_oid) ⇒ Hash<String, Int>
Get the count of commits by author from the head to the specified oid.
- #available_branches ⇒ nil, Array<String>
- #available_remotes ⇒ nil, Array<String>
- #blob_at(relative_path, ref) ⇒ Object
-
#commit ⇒ nil, Boolean
Commit the working directory.
-
#commits_for(relative_path, limit) ⇒ Array<Rugged::Commit>
Excluding the initial commit (without a parent) which keeps things consistent with the original behaviour.
- #current_oid ⇒ nil, String
-
#dirty? ⇒ Boolean
Is the working directory dirty.
-
#fetch ⇒ nil, ...
Fetch all the remote branches.
- #grep(term) {|file, context| ... } ⇒ Object
-
#initialize(path_or_share) ⇒ Repository
constructor
Initialize the repository on the specified path.
- #last_commit_for(relative_path) ⇒ Rugged::Commit
-
#merge ⇒ nil, ...
Merge the repository.
- #need_sync? ⇒ Boolean
-
#push ⇒ nil, ...
Push the repository.
- #root ⇒ String
- #valid? ⇒ Boolean
- #write_commit_message(message) ⇒ Object
Constructor Details
#initialize(path_or_share) ⇒ Repository
Initialize the repository on the specified path. If the path is not valid for some reason, the object will be initialized but it will be put into an invalid state.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/gitdocs/repository.rb', line 25 def initialize(path_or_share) path = path_or_share if path_or_share.respond_to?(:path) path = path_or_share.path @remote_name = path_or_share.remote_name @branch_name = path_or_share.branch_name end @rugged = Rugged::Repository.new(path) @grit = Grit::Repo.new(path) Grit::Git.git_timeout = 120 @invalid_reason = nil = abs_path('.gitmessage~') rescue Rugged::OSError @invalid_reason = :directory_missing rescue Rugged::RepositoryError @invalid_reason = :no_repository end |
Instance Attribute Details
#invalid_reason ⇒ Object (readonly)
Returns the value of attribute invalid_reason.
16 17 18 |
# File 'lib/gitdocs/repository.rb', line 16 def invalid_reason @invalid_reason end |
Class Method Details
.clone(path, remote) ⇒ Gitdocs::Repository
Clone a repository, and create the destination path if necessary.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/gitdocs/repository.rb', line 52 def self.clone(path, remote) FileUtils.mkdir_p(File.dirname(path)) # TODO: determine how to do this with rugged, and handle SSH and HTTPS # credentials. Grit::Git.new(path).clone({ raise: true, quiet: true }, remote, path) repository = new(path) fail("Unable to clone into #{path}") unless repository.valid? repository rescue Grit::Git::GitTimeout raise("Unable to clone into #{path} because it timed out") rescue Grit::Git::CommandFailed => e raise("Unable to clone into #{path} because of #{e.err}") end |
Instance Method Details
#author_count(last_oid) ⇒ Hash<String, Int>
Get the count of commits by author from the head to the specified oid.
235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/gitdocs/repository.rb', line 235 def (last_oid) walker = head_walker walker.hide(last_oid) if last_oid walker.reduce(Hash.new(0)) do |result, commit| result["#{commit.author[:name]} <#{commit.author[:email]}>"] += 1 result end rescue Rugged::ReferenceError {} rescue Rugged::OdbError {} end |
#available_branches ⇒ nil, Array<String>
87 88 89 90 |
# File 'lib/gitdocs/repository.rb', line 87 def available_branches return nil unless valid? Rugged::Branch.each_name(@rugged, :local).sort end |
#available_remotes ⇒ nil, Array<String>
80 81 82 83 |
# File 'lib/gitdocs/repository.rb', line 80 def available_remotes return nil unless valid? Rugged::Branch.each_name(@rugged, :remote).sort end |
#blob_at(relative_path, ref) ⇒ Object
284 285 286 |
# File 'lib/gitdocs/repository.rb', line 284 def blob_at(relative_path, ref) @rugged.blob_at(ref, relative_path) end |
#commit ⇒ nil, Boolean
Commit the working directory
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/gitdocs/repository.rb', line 189 def commit return nil unless valid? # Do this first to allow the message file to be deleted, if it exists. = mark_empty_directories return false unless dirty? # Commit any changes in the working directory. Dir.chdir(root) do @rugged.index.add_all @rugged.index.update_all end @rugged.index.write @grit.commit_index() true end |
#commits_for(relative_path, limit) ⇒ Array<Rugged::Commit>
Excluding the initial commit (without a parent) which keeps things consistent with the original behaviour. TODO: reconsider if this is the correct behaviour
264 265 266 267 268 269 270 271 272 273 |
# File 'lib/gitdocs/repository.rb', line 264 def commits_for(relative_path, limit) # TODO: should add a filter here for checking that the commit actually has # an associated blob. commits = head_walker.select do |commit| commit.parents.size == 1 && commit.diff(paths: [relative_path]).size > 0 end # TODO: should re-write this limit in a way that will skip walking all of # the commits. commits.first(limit) end |
#current_oid ⇒ nil, String
94 95 96 97 98 |
# File 'lib/gitdocs/repository.rb', line 94 def current_oid @rugged.head.target rescue Rugged::ReferenceError nil end |
#dirty? ⇒ Boolean
Is the working directory dirty
103 104 105 106 107 108 |
# File 'lib/gitdocs/repository.rb', line 103 def dirty? return false unless valid? return Dir.glob(abs_path('*')).any? unless current_oid @rugged.diff_workdir(current_oid, include_untracked: true).deltas.any? end |
#fetch ⇒ nil, ...
Fetch all the remote branches
143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/gitdocs/repository.rb', line 143 def fetch return nil unless valid? return :no_remote unless remote? @rugged.remotes.each { |x| @grit.remote_fetch(x.name) } :ok rescue Grit::Git::GitTimeout "Fetch timed out for #{root}" rescue Grit::Git::CommandFailed => e e.err end |
#grep(term) {|file, context| ... } ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/gitdocs/repository.rb', line 123 def grep(term, &block) @grit.git.grep( { raise: true, bare: false, chdir: root, ignore_case: true }, term ).scan(/(.*?):([^\n]*)/, &block) rescue Grit::Git::GitTimeout # TODO: add logging to record the error details '' rescue Grit::Git::CommandFailed # TODO: add logging to record the error details if they are not just # nothing found '' end |
#last_commit_for(relative_path) ⇒ Rugged::Commit
278 279 280 |
# File 'lib/gitdocs/repository.rb', line 278 def last_commit_for(relative_path) head_walker.find { |commit| commit.diff(paths: [relative_path]).size > 0 } end |
#merge ⇒ nil, ...
Merge the repository
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/gitdocs/repository.rb', line 163 def merge return nil unless valid? return :no_remote unless remote? return :ok unless remote_branch return :ok if remote_branch.tip.oid == current_oid @grit.git.merge( { raise: true, chdir: root }, "#{@remote_name}/#{@branch_name}" ) :ok rescue Grit::Git::GitTimeout "Merge timed out for #{root}" rescue Grit::Git::CommandFailed => e # HACK: The rugged in-memory index will not have been updated after the # Grit merge command. Reload it before checking for conflicts. @rugged.index.reload return e.err unless @rugged.index.conflicts? mark_conflicts end |
#need_sync? ⇒ Boolean
111 112 113 114 115 116 117 |
# File 'lib/gitdocs/repository.rb', line 111 def need_sync? return false unless valid? return false unless remote? return !!current_oid unless remote_branch # rubocop:disable DoubleNegation remote_branch.tip.oid != current_oid end |
#push ⇒ nil, ...
Push the repository
216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/gitdocs/repository.rb', line 216 def push return nil unless valid? return :no_remote unless remote? return :nothing if current_oid.nil? return :nothing if remote_branch && remote_branch.tip.oid == current_oid @grit.git.push({ raise: true }, @remote_name, @branch_name) :ok rescue Grit::Git::CommandFailed => e return :conflict if e.err[/\[rejected\]/] e.err # return the output on error end |
#root ⇒ String
68 69 70 71 |
# File 'lib/gitdocs/repository.rb', line 68 def root return nil unless valid? @rugged.path.sub(/.\.git./, '') end |
#valid? ⇒ Boolean
74 75 76 |
# File 'lib/gitdocs/repository.rb', line 74 def valid? !@invalid_reason end |
#write_commit_message(message) ⇒ Object
249 250 251 252 253 254 |
# File 'lib/gitdocs/repository.rb', line 249 def () return unless return if .empty? File.open(, 'w') { |f| f.print() } end |