Module: Amp::Repositories::CommonStagingAreaMethods

Included in:
AbstractStagingArea
Defined in:
lib/amp/repository/abstract/common_methods/staging_area.rb

Overview

CommonStagingAreaMethods

These methods are common to all staging areas, and this module is mixed into the AbstractStagingArea class. This guarantees that all staging areas will have these methods.

No methods should be placed into this module unless it relies on methods in the general API for staging areas.

Instance Method Summary collapse

Instance Method Details

#examine_named_files(files, match) ⇒ Array<Hash, Array<String>>

TODO:

this is still tied to hg

Helper method that filters out a list of explicit filenames that do not belong in the repository. It then stores the File stats of the files it keeps, and returns any explicitly named directories.

Parameters:

Returns:



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
# File 'lib/amp/repository/abstract/common_methods/staging_area.rb', line 34

def examine_named_files(files, match)
  results, work = {vcs_dir => true}, [] # ignore the .hg
  files.reject {|f| results[f] || f == ""}.sort.each do |file|
    path  = File.join(repo.root, file)
    
    if File.exist?(path)
      # we'll take it! but only if it's a directory, which means we have
      # more work to do...
      if File.directory?(path)
        # add it to the list of dirs we have to search in
        work << File.join(repo.root, file) unless ignoring_directory? file
      elsif File.file?(path) || File.symlink?(path)
        # ARGH WE FOUND ZE BOOTY
        results[file] = File.lstat path
      else
        # user you are a fuckup in life please exit the world
        UI::warn "#{file}: unsupported file type (type is #{File.ftype file})"
        results[file] = nil if tracking? file
      end
    else
      prefix = file + '/'
      
      unless all_files.find { |f, _| f == file || f.start_with?(prefix) }
        bad_type[file]
        results[file] = nil if (tracking?(file) || !ignoring_file?(file)) && match.call(file)
      end
    end
  end
  [results, work]
end

#find_with_patterns(found_files, dirs, match) ⇒ Hash

Helper method that runs match’s patterns on every non-ignored file in the repository’s directory.

Parameters:

  • found_files (Hash)

    the already found files (we don’t want to search them again)

  • dirs (Array<String>)

    the directories to search

  • match (Amp::Match)

    the matcher object that runs patterns against filenames

Returns:

  • (Hash)

    the updated found_files hash



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/amp/repository/abstract/common_methods/staging_area.rb', line 75

def find_with_patterns(found_files, dirs, match)
  results = found_files
  Find.find(*dirs) do |f|
    tf = f[(repo.root.size+1)..-1]
    Find.prune if results[tf]
    
    stats = File.lstat f
    match_result = match.call tf
    tracked = tracking? tf
    
    if File.directory? f
      Find.prune if ignoring_file? tf
      results[tf] = nil if tracked && match_result
    elsif File.file?(f) || File.symlink?(f)
      if match_result && (tracked || !ignoring_file?(tf))
        results[tf] = stats
      end
    elsif tracked && match_result
      results[tf] = nil
    end
  end
  results
end

#status(ignored, clean, unknown, match = Match.new { true }) ⇒ Hash<Symbol => Array<String>>

what’s the current state of life, man! Splits up all the files into modified, clean, added, deleted, unknown, ignored, or lookup-needed.

Parameters:

  • ignored (Boolean)

    do we collect the ignore files?

  • clean (Boolean)

    do we collect the clean files?

  • unknown (Boolean)

    do we collect the unknown files?

  • match (Amp::Match) (defaults to: Match.new { true })

    the matcher

Returns:



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
# File 'lib/amp/repository/abstract/common_methods/staging_area.rb', line 156

def status(ignored, clean, unknown, match = Match.new { true })
  list_ignored, list_clean, list_unknown = ignored, clean, unknown
  lookup, modified, added, unknown, ignored = [], [], [], [], []
  moved, copied, removed, deleted, clean = [], [], [], [], []
  delta = 0

  walk(list_unknown, list_ignored, match).each do |file, st|
    next if file.nil?
    
    unless tracking?(file)
      if list_ignored && ignoring_directory?(file)
        ignored << file
      elsif list_unknown
        unknown << file unless ignoring_file?(file)
      end
    
      next # on to the next one, don't do the rest
    end
  
    # here's where we split up the files
    state = file_status file
    
    delta += calculate_delta(file, st)
    if !st && [:normal, :modified, :added].include?(state)
      # add it to the deleted folder if it should be here but isn't
      deleted << file
    elsif state == :normal
      case file_precise_status(file, st)
      when :modified
        modified << file
      when :lookup
        lookup << file
      when :clean
        clean << file if list_clean
      end
    
    elsif state == :merged
      modified << file
    elsif state == :added
      added << file
    elsif state == :removed
      removed << file
    end
  end
  
  # # This code creates the copied and moved arrays
  # # 
  # # ugh this should be optimized
  # # as in, built into the code above ^^^^^
  # dirstate.copy_map.each do |dst, src|
  #   # assume that if +src+ is in +removed+ then +dst+ is in +added+
  #   # we know that this part will be COPIES
  #   if removed.include? src
  #     removed.delete src
  #     added.delete   dst
  #     copied << [src, dst]
  #   elsif added.include? dst # these are the MOVES
  #     added.delete dst
  #     moved << [src, dst]
  #   end
  # end

  r = { :modified => modified.sort , # those that have clearly been modified
        :added    => added.sort    , # those that are marked for adding
        :removed  => removed.sort  , # those that are marked for removal
        :deleted  => deleted.sort  , # those that should be here but aren't
        :unknown  => unknown.sort  , # those that aren't being tracked
        :ignored  => ignored.sort  , # those that are being deliberately ignored
        :clean    => clean.sort    , # those that haven't changed
        :lookup   => lookup.sort   , # those that need to be content-checked to see if they've changed
        #:copied   => copied.sort_by {|a| a[0] }, # those that have been copied
        #:moved    => moved.sort_by  {|a| a[0] }, # those that have been moved
        :delta    => delta           # how many bytes have been added or removed from files (not bytes that have been changed)
      }
end

#tracking?(filename) ⇒ Boolean

Returns whether or not the repository is tracking the given file.

Parameters:

  • filename (String)

    the file to look up

Returns:

  • (Boolean)

    are we tracking the given file?



21
22
23
# File 'lib/amp/repository/abstract/common_methods/staging_area.rb', line 21

def tracking?(filename)
  file_status(filename) != :untracked
end

#walk(unknown, ignored, match = Amp::Match.new { true }) ⇒ Hash<String => [NilClass, File::Stat]>

TODO:

this is still tied to hg

Walk recursively through the directory tree, finding all files matched by the regexp in match.

Step 1: find all explicit files Step 2: visit subdirectories Step 3: report unseen items in the @files hash

Parameters:

Returns:



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
# File 'lib/amp/repository/abstract/common_methods/staging_area.rb', line 112

def walk(unknown, ignored, match = Amp::Match.new { true })
  if ignored
    @ignore_all = false
  elsif not unknown
    @ignore_all = true
  end
  
  files = (match.files || []).uniq
  
  # why do we overwrite the entire array if it includes the current dir?
  # we even kill posisbly good things
  files = [''] if files.include?('.') # strange thing to do
  
  # Step 1: find all explicit files
  results, found_directories = examine_named_files files, match
  work = [repo.root] + found_directories
  
  # Run the patterns
  results = find_with_patterns(results, work, match)
  
  # step 3: report unseen items in @files
  visit = all_files.select {|f| !results[f] && match.call(f) }.sort
  
  visit.each do |file|
    path = File.join(repo.root, file)
    keep = File.exist?(path) && (File.file?(path) || File.symlink(path))
    results[file] = keep ? File.lstat(path) : nil
  end
  
  results.delete vcs_dir
  @ignore_all = nil # reset this
  results
end