Class: BuildTool::VCS::Git

Inherits:
Base
  • Object
show all
Defined in:
lib/build-tool/vcs/git.rb

Overview

Implementation for the git version control system.

Instance Attribute Summary

Attributes inherited from Base

#config

Instance Method Summary collapse

Methods inherited from Base

#apply_patches_after_rebase?, #check_for_sshkey, #configure, #local_changes, #local_path, #local_path_exist?, #patches_supported?, #prepare_for_rebase, #recipe, #remote_changes

Constructor Details

#initialize(config) ⇒ Git

Returns a new instance of Git.



224
225
226
227
228
# File 'lib/build-tool/vcs/git.rb', line 224

def initialize( config )
    super( config )
    @remote = {}
    @vcs = nil
end

Instance Method Details

#check_configObject



351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/build-tool/vcs/git.rb', line 351

def check_config
    return if @already_checked_config
    if checkedout?
        # Check that the remotes are the same as configured.
        gitconfig = Grit::RepoConfig.new(repo)
        config.merged_remote.each do |name, val|
            if val.url
                if gitconfig["remote.#{name}.url"].nil?
                    if git( "remote add #{name} #{val.url}" ) != 0
                        raise GitError, "Error while initializing the repo `git remote add #{name} #{val.url}`: #{$?}"
                    end
                elsif val.url != gitconfig["remote.#{name}.url"]
                    logger.info "repo: Setting remote.origin.url to #{val.url}"
                    gitconfig["remote.#{name}.url"] = val.url
                end
            end

            if val.push_server and val.push_url
                if val.push_url != gitconfig["remote.#{name}.pushurl"]
                    if git( "remote set-url --push #{name} #{val.push_url}" ) != 0
                        raise GitError, "Error while initializing the repo `git remote add #{name} #{val.url}`: #{$?}"
                    end
                elsif val.push_url != gitconfig["remote.#{name}.pushurl"]
                    logger.info "repo: Setting remote.origin.pushurl to #{val.push_url}"
                    gitconfig["remote.#{name}.pushurl"] = val.push_url
                end
            end
        end

        # Check that the options are the same as configured.
        config.merged_options.each do |name, val|
            if val != gitconfig[name]
                if val.empty?
                    next if gitconfig[name].nil?
                    logger.info "repo: git-config: Removing #{name}"
                    gitconfig.delete name if !$noop
                else
                    logger.info "repo: git-config: Setting #{name} to #{val}"
                    gitconfig[name] = val if !$noop
                end
            end
        end

        # Check if there is a commit template. If yes add it.
        if ( not gitconfig["commit.template"] and not config.merged_options["commit.template"] ) and Pathname.new( local_path ).join( '.commit-template' ).exist?
            logger.info "#{config.module.name}: git-config: Setting commit.template to .commit-template"
            gitconfig["commit.template"] = ".commit-template" if !$noop

        end
        @already_checked_config = true
    end
end

#check_user_configObject



325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/build-tool/vcs/git.rb', line 325

def check_user_config
    return if @already_checked_user_config
    # :FIXME: It would make sense to do this even if the repo is not existing but grit cannot
    # handle that
    if checkedout?
        # Check that the options are the same as configured.
        if ! GitConfiguration.global_config_checked
            gitconfig = Grit::UserConfig.new(repo)
            config.merged_global_options.each do |name, val|
                if val != gitconfig[name]
                    if val.empty?
                        next if gitconfig[name].nil?
                        logger.info "repo: git-config: Removing #{name}"
                        gitconfig.delete name if !$noop
                    else
                        logger.info "repo: git-config: Setting #{name} to #{val}"
                        gitconfig[name] = val if !$noop
                    end
                end
            end
            GitConfiguration.global_config_checked = true
        end
    end
    @already_checked_user_config = true
end

#checkedout?Boolean

METHODS

Returns:

  • (Boolean)


255
256
257
258
259
260
261
# File 'lib/build-tool/vcs/git.rb', line 255

def checkedout?
    return false if !local_path_exist?
    if !Pathname.new( local_path ).join( ".git" ).exist?
        raise Base::VcsError, "Checkout path #{local_path} is not a git repo!"
    end
    return true
end

#cloneObject

Initialize the local repository



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/build-tool/vcs/git.rb', line 264

def clone
    # Check if path exists
    if local_path_exist?
        raise GitError, "Failed to create repository at '#{local_path}': Path exists"
    end

    # Create the directory
    FileUtils.mkdir_p( local_path ) if !$noop

    # Initialize the repository
    if git( "init", local_path ) != 0
        raise GitError, "Error while initializing the repo `git init #{local_path}'`: #{$?}"
    end

    check_config

    logger.info <<-EOS
The following command sometimes fails when issued from this script. Reason unknown. The
best chance you have is issuing the command manually!
#{local_path}: git fetch #{config.track_remote}
#{local_path}: git checkout -b #{config.track_branch} #{config.track_remote}/#{config.track_branch}
    EOS

    fetch()

    cmd = "checkout -b #{config.track_branch} #{config.track_remote}/#{config.track_branch}"
    if git( cmd, local_path ) != 0
        raise GitError, "Error while initializing the repo `#{cmd}`: #{$?}"
    end

end

#dirty?Boolean

Check if the checkout is dirty.

Returns:

  • (Boolean)


414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/build-tool/vcs/git.rb', line 414

def dirty?
    # Check if the index is dirty.
    if git( "diff --exit-code" ) != 0
        return true
    end

    if git( "diff --cached --exit-code" ) != 0
        return true
    end

    return false
end

#do_local_changes(&block) ⇒ Object

Print the unpushed changes.



454
455
456
457
# File 'lib/build-tool/vcs/git.rb', line 454

def do_local_changes( &block )
    remote_branch = "#{config.track_remote}/#{config.track_branch}"
    git('log --first-parent --pretty=oneline %s..HEAD' % remote_branch, &block )
end

#do_remote_changes(&block) ⇒ Object

Print the pending changes.



446
447
448
449
# File 'lib/build-tool/vcs/git.rb', line 446

def do_remote_changes( &block )
    remote_branch = "#{config.track_remote}/#{config.track_branch}"
    git('log --first-parent --pretty=oneline HEAD..%s' % remote_branch, &block )
end

#fetch(verbose = false) ⇒ Object

Fetch from repository

Initializes the local clone if it does not exist.



303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/build-tool/vcs/git.rb', line 303

def fetch( verbose = false )
    if !checkedout? and !$noop
        clone
    else
        # clone() calls those methods.
        check_config
    end
    cmd = "fetch -q --prune #{config.track_remote}"
    if ( rc = git( cmd ) ) != 0
        raise GitError, "Error while fetching: #{rc}"
    end
end

#fetching_supported?Boolean

Returns:

  • (Boolean)


242
243
244
# File 'lib/build-tool/vcs/git.rb', line 242

def fetching_supported?
    true
end

#gcObject



296
297
298
# File 'lib/build-tool/vcs/git.rb', line 296

def gc
    git( "gc" )
end

#git(command, wd = local_path, &block) ⇒ Object



316
317
318
# File 'lib/build-tool/vcs/git.rb', line 316

def git( command, wd = local_path, &block )
    self.class.execute "git #{command}", wd, &block
end

#nameObject

ATTRIBUTES



238
239
240
# File 'lib/build-tool/vcs/git.rb', line 238

def name
    "git"
end

#prepare_for_fetchObject



320
321
322
323
# File 'lib/build-tool/vcs/git.rb', line 320

def prepare_for_fetch
    # If our server has an associated ssh-key, add it to the ssh-agent.
    return check_for_sshkey( config.merged_remote[ config.track_remote ].server.sshkey )
end

#ready_for_fetchObject



404
405
406
407
408
409
410
411
# File 'lib/build-tool/vcs/git.rb', line 404

def ready_for_fetch
    if not MJ::VCS::Git.git_available?
        logger.error( "#{config.module.name}: Calling `git` failed!" )
        return false
    end

    return true
end

#ready_for_rebaseObject

Check if the module is ready for a rebase.



428
429
430
431
432
433
434
435
436
437
438
439
440
441
# File 'lib/build-tool/vcs/git.rb', line 428

def ready_for_rebase
    check_user_config
    if checkedout?
        # Check if the index is dirty.
        if dirty?
            logger.info( "#{config.module.name}: A dirty index will prevent the rebase." )
            git( "status -s -uno" ) do |line|
                logger.info line.chomp
            end
            return false
        end
    end
    true
end

#rebase(verbose = false) ⇒ Object



459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/build-tool/vcs/git.rb', line 459

def rebase( verbose = false )
    check_config
    remote_branch = "#{config.track_remote}/#{config.track_branch}"

    if verbose
        remote_changes.each do |line|
            logger.info( line )
        end
    end

    if 0 != ( git "rebase #{remote_branch}" )
        raise GitError, "Error while rebasing the repo with `#{remote_branch}': #{$?}"
    end
end

#repoObject



246
247
248
249
250
# File 'lib/build-tool/vcs/git.rb', line 246

def repo
    return @repo if @repo
    @repo = Grit::Repo.new( local_path )
    @repo
end