File: repository.rb

package info (click to toggle)
ruby-rugged 1.9.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,752 kB
  • sloc: ansic: 8,722; ruby: 7,473; sh: 99; makefile: 5
file content (274 lines) | stat: -rw-r--r-- 8,547 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# Copyright (C) the Rugged contributors.  All rights reserved.
#
# This file is part of Rugged, distributed under the MIT license.
# For full terms see the included LICENSE file.

module Rugged
  # Repository is an interface into a Git repository on-disk. It's the primary
  # interface between your app and the main Git objects Rugged makes available
  # to you.
  class Repository
    # Pretty formatting of a Repository.
    #
    # Returns a very pretty String.
    def inspect
      "#<Rugged::Repository:#{object_id} {path: #{path.inspect}}>"
    end

    # Get the most recent commit from this repo.
    #
    # Returns a Rugged::Commit object.
    def last_commit
      self.head.target
    end

    # Checkout the specified branch, reference or commit.
    #
    # target - A revparse spec for the branch, reference or commit to check out.
    # options - Options passed to #checkout_tree.
    def checkout(target, options = {})
      options[:strategy] ||= :safe
      options.delete(:paths)

      return checkout_head(**options) if target == "HEAD"

      if target.kind_of?(Rugged::Branch)
        branch = target
      else
        branch = branches[target]
      end

      if branch
        self.checkout_tree(branch.target, **options)

        if branch.remote?
          references.create("HEAD", branch.target_id, force: true)
        else
          references.create("HEAD", branch.canonical_name, force: true)
        end
      else
        commit = Commit.lookup(self, self.rev_parse_oid(target))
        references.create("HEAD", commit.oid, force: true)
        self.checkout_tree(commit, **options)
      end
    end

    ###
    #  call-seq:
    #    repo.status { |file, status_data| block }
    #    repo.status(path) -> status_data
    #
    #  Returns the status for one or more files in the working directory
    #  of the repository. This is equivalent to the +git status+ command.
    #
    #  The returned +status_data+ is always an array containing one or more
    #  status flags as Ruby symbols. Possible flags are:
    #
    #  - +:index_new+: the file is new in the index
    #  - +:index_modified+: the file has been modified in the index
    #  - +:index_deleted+: the file has been deleted from the index
    #  - +:worktree_new+: the file is new in the working directory
    #  - +:worktree_modified+: the file has been modified in the working directory
    #  - +:worktree_deleted+: the file has been deleted from the working directory
    #
    #  If a +block+ is given, status information will be gathered for every
    #  single file on the working dir. The +block+ will be called with the
    #  status data for each file.
    #
    #    repo.status { |file, status_data| puts "#{file} has status: #{status_data.inspect}" }
    #
    #  results in, for example:
    #
    #    src/diff.c has status: [:index_new, :worktree_new]
    #    README has status: [:worktree_modified]
    #
    #  If a +path+ is given instead, the function will return the +status_data+ for
    #  the file pointed to by path, or raise an exception if the path doesn't exist.
    #
    #  +path+ must be relative to the repository's working directory.
    #
    #    repo.status('src/diff.c') #=> [:index_new, :worktree_new]
    def status(file = nil, &block)
      if file
        file_status file
      else
        each_status(&block)
      end
    end

    def diff(left, right, opts = {})
      left = rev_parse(left) if left.kind_of?(String)
      right = rev_parse(right) if right.kind_of?(String)

      if !left.is_a?(Rugged::Tree) && !left.is_a?(Rugged::Commit) && !left.nil?
        raise TypeError, "Expected a Rugged::Tree or Rugged::Commit instance"
      end

      if !right.is_a?(Rugged::Tree) && !right.is_a?(Rugged::Commit) && !right.nil?
        raise TypeError, "Expected a Rugged::Tree or Rugged::Commit instance"
      end

      if left
        left.diff(right, opts)
      elsif right
        right.diff(left, opts.merge(:reverse => !opts[:reverse]))
      end
    end

    def diff_workdir(left, opts = {})
      left = rev_parse(left) if left.kind_of?(String)

      if !left.is_a?(Rugged::Tree) && !left.is_a?(Rugged::Commit)
        raise TypeError, "Expected a Rugged::Tree or Rugged::Commit instance"
      end

      left.diff_workdir(opts)
    end

    # Walks over a set of commits using Rugged::Walker.
    #
    # from    - The String SHA1 to push onto Walker to begin our walk.
    # sorting - The sorting order of the commits, as defined in the README.
    # block   - A block that we pass into walker#each.
    #
    # Returns nothing if called with a block, otherwise returns an instance of
    # Enumerable::Enumerator containing Rugged::Commit objects.
    def walk(from, sorting=Rugged::SORT_DATE, &block)
      walker = Rugged::Walker.new(self)
      walker.sorting(sorting)
      walker.push(from)
      walker.each(&block)
    end

    # Look up a SHA1.
    #
    # Returns one of the four classes that inherit from Rugged::Object.
    def lookup(oid)
      Rugged::Object.lookup(self, oid)
    end

    # Look up an object by a revision string.
    #
    # Returns one of the four classes that inherit from Rugged::Object.
    def rev_parse(spec)
      Rugged::Object.rev_parse(self, spec)
    end

    # Look up an object by a revision string.
    #
    # Returns the oid of the matched object as a String
    def rev_parse_oid(spec)
      Rugged::Object.rev_parse_oid(self, spec)
    end

    # Look up a single reference by name.
    #
    # Example:
    #
    #   repo.ref 'refs/heads/master'
    #   # => #<Rugged::Reference:2199125780 {name: "refs/heads/master",
    #          target: "25b5d3b40c4eadda8098172b26c68cf151109799"}>
    #
    # Returns a Rugged::Reference.
    def ref(ref_name)
      references[ref_name]
    end

    def refs(glob = nil)
      references.each(glob)
    end

    def references
      @references ||= ReferenceCollection.new(self)
    end

    def ref_names(glob = nil)
      references.each_name(glob)
    end

    # All the tags in the repository.
    #
    # Returns a TagCollection containing all the tags.
    def tags
      @tags ||= TagCollection.new(self)
    end

    # All the remotes in the repository.
    #
    # Returns a Rugged::RemoteCollection containing all the Rugged::Remote objects
    # in the repository.
    def remotes
      @remotes ||= RemoteCollection.new(self)
    end

    # All the branches in the repository
    #
    # Returns a BranchCollection containing Rugged::Branch objects
    def branches
      @branches ||= BranchCollection.new(self)
    end

    # All the submodules in the repository
    #
    # Returns a SubmoduleCollection containing Rugged::Submodule objects
    def submodules
      @submodules ||= SubmoduleCollection.new(self)
    end

    # Create a new branch in the repository
    #
    # name - The name of the branch (without a full reference path)
    # sha_or_ref - The target of the branch; either a String representing
    # an OID or a reference name, or a Rugged::Object instance.
    #
    # Returns a Rugged::Branch object
    def create_branch(name, sha_or_ref = "HEAD")
      case sha_or_ref
      when Rugged::Object
        target = sha_or_ref.oid
      else
        target = rev_parse_oid(sha_or_ref)
      end

      branches.create(name, target)
    end

    # Get the blob at a path for a specific revision.
    #
    # revision - The String SHA1.
    # path     - The String file path.
    #
    # Returns a Rugged::Blob object
    def blob_at(revision, path)
      tree = Rugged::Commit.lookup(self, revision).tree
      begin
        blob_data = tree.path(path)
      rescue Rugged::TreeError
        return nil
      end
      blob = Rugged::Blob.lookup(self, blob_data[:oid])
      (blob.type == :blob) ? blob : nil
    end

    def fetch(remote_or_url, *args, **kwargs)
      unless remote_or_url.kind_of? Remote
        remote_or_url = remotes[remote_or_url] || remotes.create_anonymous(remote_or_url)
      end
      remote_or_url.fetch(*args, **kwargs)
    end

    # Push a list of refspecs to the given remote.
    #
    # refspecs - A list of refspecs that should be pushed to the remote.
    #
    # Returns a hash containing the pushed refspecs as keys and
    # any error messages or +nil+ as values.
    def push(remote_or_url, *args, **kwargs)
      unless remote_or_url.kind_of? Remote
        remote_or_url = remotes[remote_or_url] || remotes.create_anonymous(remote_or_url)
      end

      remote_or_url.push(*args, **kwargs)
    end
  end
end