Class: Omnibus::GitFetcher

Inherits:
Fetcher
  • Object
show all
Defined in:
lib/omnibus/fetchers/git_fetcher.rb

Constant Summary

Constants included from Util

Util::SHELLOUT_OPTIONS

Instance Attribute Summary

Attributes inherited from Fetcher

#build_dir, #described_version, #name, #project_dir, #resolved_version, #source

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Fetcher

#fetcher, #initialize, #version

Methods included from Util

#copy_file, #create_directory, #create_file, #create_link, included, #remove_directory, #remove_file, #shellout, #shellout!, #windows_safe_path

Methods included from Logging

included

Methods included from Digestable

#digest, #digest_directory, included

Constructor Details

This class inherits a constructor from Omnibus::Fetcher

Class Method Details

.dereference_annotated_tag(remote_list, ref) ⇒ String

Dereference annotated tags.

The remote_list parameter is assumed to look like this:

a2ed66c01f42514bcab77fd628149eccb4ecee28        refs/tags/rel-0.11.0
f915286abdbc1907878376cce9222ac0b08b12b8        refs/tags/rel-0.11.0^{}

The SHA with ^{} is the commit pointed to by an annotated tag. If ref isn't an annotated tag, there will not be a line with trailing ^{}.

Parameters:

  • remote_list (String)

    output from `git ls-remote origin` command

  • ref (String)

    the target git ref

Returns:

  • (String)

267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 267

def self.dereference_annotated_tag(remote_list, ref)
  # We'll return the SHA corresponding to the ^{} which is the
  # commit pointed to by an annotated tag. If no such commit
  # exists (not an annotated tag) then we return the SHA of the
  # ref.  If nothing matches, return "".
  lines = remote_list.split("\n")
  matches = lines.map { |line| line.split("\t") }
  # First try for ^{} indicating the commit pointed to by an
  # annotated tag.
  tagged_commit = matches.find { |m| m[1].end_with?("#{ref}^{}") }
  if tagged_commit
    tagged_commit.first
  else
    found = matches.find { |m| m[1].end_with?("#{ref}") }
    if found
      found.first
    else
      nil
    end
  end
end

.resolve_version(ref, source) ⇒ String

Return the SHA1 corresponding to a ref as determined by the remote source.

Returns:

  • (String)

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 199

def self.resolve_version(ref, source)
  if sha_hash?(ref)
    # A git server negotiates in terms of refs during the info-refs phase
    # of a fetch. During upload-pack, the client is not allowed to specify
    # any sha1s in the "wants" unless the server has publicized them during
    # info-refs. Hence, the server is allowed to drop requests to fetch
    # particular sha1s, even if it is an otherwise reachable commit object.
    # Only when the service is specifically configured with
    # uploadpack.allowReachableSHA1InWant is there any guarantee that it
    # considers "naked" wants.
    log.warn(log_key) { 'git fetch on a sha1 is not guaranteed to work' }
    log.warn(log_key) { "Specify a ref name instead of #{ref} on #{source}" }
    ref
  else
    revision_from_remote_reference(ref, source)
  end
end

.revision_from_remote_reference(ref, source) ⇒ String

Return the SHA corresponding to ref.

If ref is an annotated tag, return the SHA that was tagged not the SHA of the tag itself.

Returns:

  • (String)

234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 234

def self.revision_from_remote_reference(ref, source)
  # execute `git ls-remote` the trailing '*' does globbing. This
  # allows us to return the SHA of the tagged commit for annotated
  # tags. We take care to only return exact matches in
  # process_remote_list.
  remote_list = shellout!("git ls-remote \"#{source[:git]}\" #{ref}*").stdout
  commit_ref = dereference_annotated_tag(remote_list, ref)

  unless commit_ref
    raise UnresolvableGitReference.new(ref)
  end
  commit_ref
end

.sha_hash?(rev) ⇒ true, false

Determine if the given revision is a SHA

Returns:

  • (true, false)

222
223
224
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 222

def self.sha_hash?(rev)
  rev =~ /^[0-9a-f]{4,40}$/i
end

Instance Method Details

#cleantrue, false

Clean the project directory by removing the contents from disk.

Returns:

  • (true, false)

    true if the project directory was removed, false otherwise


45
46
47
48
49
50
51
52
53
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 45

def clean
  if cloned?
    log.info(log_key) { 'Cleaning existing clone' }
    git('clean -fdx')
    true
  else
    false
  end
end

#fetchvoid

This method returns an undefined value.

Fetch (clone) or update (fetch) the remote git repository.


60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 60

def fetch
  log.info(log_key) { "Fetching from `#{source_url}'" }
  create_required_directories

  if cloned?
    git_fetch unless same_revision?(resolved_version)
  else
    force_recreate_project_dir! unless dir_empty?(project_dir)
    git_clone
    git_checkout
  end
end

#fetch_required?true, false

A fetch is required if the git repository is not cloned or if the local revision does not match the desired revision.

Returns:

  • (true, false)

25
26
27
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 25

def fetch_required?
  !(cloned? && same_revision?(resolved_version))
end

#version_for_cacheString

The version for this item in the cache. The is the parsed revision of the item on disk.

Returns:

  • (String)

79
80
81
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 79

def version_for_cache
  "revision:#{current_revision}"
end

#version_guidString

The version identifier for this git location. This is computed using the current revision on disk.

Returns:

  • (String)

35
36
37
# File 'lib/omnibus/fetchers/git_fetcher.rb', line 35

def version_guid
  "git:#{current_revision}"
end