File: tree.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 (197 lines) | stat: -rw-r--r-- 7,054 bytes parent folder | download
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
# 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
  class Tree
    ##
    # call-seq:
    #   Tree.diff(repo, tree, diffable[, options]) -> diff
    #
    # Returns a diff between the `tree` and the diffable object that was given.
    # +diffable+ can either be a +Rugged::Commit+, a +Rugged::Tree+, a +Rugged::Index+,
    # or +nil+.
    #
    # The +tree+ object will be used as the "old file" side of the diff, while the
    # parent tree or the +diffable+ object will be used for the "new file" side.
    #
    # If +tree+ or +diffable+ are nil, they will be treated as an empty tree. Passing
    # both as `nil` will raise an exception.
    #
    # The following options can be passed in the +options+ Hash:
    #
    # :paths ::
    #   An array of paths / fnmatch patterns to constrain the diff to a specific
    #   set of files. Also see +:disable_pathspec_match+.
    #
    # :max_size ::
    #   An integer specifying the maximum byte size of a file before a it will
    #   be treated as binary. The default value is 512MB.
    #
    # :context_lines ::
    #   The number of unchanged lines that define the boundary of a hunk (and
    #   to display before and after the actual changes). The default is 3.
    #
    # :interhunk_lines ::
    #   The maximum number of unchanged lines between hunk boundaries before the hunks
    #   will be merged into a one. The default is 0.
    #
    # :old_prefix ::
    #   The virtual "directory" to prefix to old filenames in hunk headers.
    #   The default is "a".
    #
    # :new_prefix ::
    #   The virtual "directory" to prefix to new filenames in hunk headers.
    #   The default is "b".
    #
    # :reverse ::
    #   If true, the sides of the diff will be reversed.
    #
    # :force_text ::
    #   If true, all files will be treated as text, disabling binary attributes & detection.
    #
    # :ignore_whitespace ::
    #   If true, all whitespace will be ignored.
    #
    # :ignore_whitespace_change ::
    #   If true, changes in amount of whitespace will be ignored.
    #
    # :ignore_whitespace_eol ::
    #   If true, whitespace at end of line will be ignored.
    #
    # :ignore_submodules ::
    #   if true, submodules will be excluded from the diff completely.
    #
    # :patience ::
    #   If true, the "patience diff" algorithm will be used (currenlty unimplemented).
    #
    # :include_ignored ::
    #   If true, ignored files will be included in the diff.
    #
    # :include_untracked ::
    #  If true, untracked files will be included in the diff.
    #
    # :include_unmodified ::
    #   If true, unmodified files will be included in the diff.
    #
    # :recurse_untracked_dirs ::
    #   Even if +:include_untracked+ is true, untracked directories will only be
    #   marked with a single entry in the diff. If this flag is set to true,
    #   all files under ignored directories will be included in the diff, too.
    #
    # :disable_pathspec_match ::
    #   If true, the given +:paths+ will be applied as exact matches, instead of
    #   as fnmatch patterns.
    #
    # :deltas_are_icase ::
    #   If true, filename comparisons will be made with case-insensitivity.
    #
    # :show_untracked_content ::
    #   if true, untracked content will be contained in the the diff patch text.
    #
    # :skip_binary_check ::
    #   If true, diff deltas will be generated without spending time on binary
    #   detection. This is useful to improve performance in cases where the actual
    #   file content difference is not needed.
    #
    # :include_typechange ::
    #   If true, type changes for files will not be interpreted as deletion of
    #   the "old file" and addition of the "new file", but will generate
    #   typechange records.
    #
    # :include_typechange_trees ::
    #   Even if +:include_typechange+ is true, blob -> tree changes will still
    #   usually be handled as a deletion of the blob. If this flag is set to true,
    #   blob -> tree changes will be marked as typechanges.
    #
    # :ignore_filemode ::
    #   If true, file mode changes will be ignored.
    #
    # :recurse_ignored_dirs ::
    #   Even if +:include_ignored+ is true, ignored directories will only be
    #   marked with a single entry in the diff. If this flag is set to true,
    #   all files under ignored directories will be included in the diff, too.
    #
    # Examples:
    #
    #   # Emulating `git diff <treeish>`
    #   tree = Rugged::Tree.lookup(repo, "d70d245ed97ed2aa596dd1af6536e4bfdb047b69")
    #   diff = tree.diff(repo.index)
    #   diff.merge!(tree.diff)
    #
    #   # Tree-to-Tree Diff
    #   tree = Rugged::Tree.lookup(repo, "d70d245ed97ed2aa596dd1af6536e4bfdb047b69")
    #   other_tree = Rugged::Tree.lookup(repo, "7a9e0b02e63179929fed24f0a3e0f19168114d10")
    #   diff = tree.diff(other_tree)
    #

    def self.diff(repo, tree, other_tree = nil, options = {})
      if tree && !tree.is_a?(Rugged::Tree)
        raise TypeError, "At least a Rugged::Tree object is required for diffing"
      end

      if other_tree.nil?
        if tree.nil?
          raise TypeError, "Need 'old' or 'new' for diffing"
        else
          diff_tree_to_tree repo, tree, nil, options
        end
      else
        if other_tree.is_a?(::String)
          other_tree = Rugged::Object.rev_parse repo, other_tree
        end

        case other_tree
        when Rugged::Commit
          diff_tree_to_tree repo, tree, other_tree.tree, options
        when Rugged::Tree
          diff_tree_to_tree repo, tree, other_tree, options
        when Rugged::Index
          diff_tree_to_index repo, tree, other_tree, options
        else
          raise TypeError, "A Rugged::Commit, Rugged::Tree or Rugged::Index instance is required"
        end
      end
    end

    include Enumerable

    attr_reader :owner
    alias repo owner

    def diff(other = nil, options = nil)
      Tree.diff(repo, self, other, options)
    end

    def inspect
      data = "#<Rugged::Tree:#{object_id} {oid: #{oid}}>\n"
      self.each { |e| data << "  <\"#{e[:name]}\" #{e[:oid]}>\n" }
      data
    end

    # Walks the tree but only yields blobs
    def walk_blobs(mode=:postorder)
      return to_enum(__method__) unless block_given?
      self.walk(mode) { |root, e| yield root, e if e[:type] == :blob }
    end

    # Walks the tree but only yields subtrees
    def walk_trees(mode=:postorder)
      return to_enum(__method__) unless block_given?
      self.walk(mode) { |root, e| yield root, e if e[:type] == :tree }
    end

    # Iterate over the blobs in this tree
    def each_blob
      return to_enum(__method__) unless block_given?
      self.each { |e| yield e if e[:type] == :blob }
    end

    # Iterate over the subtrees in this tree
    def each_tree
      return to_enum(__method__) unless block_given?
      self.each { |e| yield e if e[:type] == :tree }
    end
  end
end