Class: Chef::Knife::CookbookSCMRepo

Inherits:
Object
  • Object
show all
Includes:
Mixin::ShellOut
Defined in:
lib/chef/knife/core/cookbook_scm_repo.rb

Constant Summary collapse

DIRTY_REPO =
/^[\s]+M/

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Mixin::ShellOut

#a_to_s, #clean_array, #shell_out, #shell_out!, #shell_out_compact, #shell_out_compact!, #shell_out_compact_timeout, #shell_out_compact_timeout!, #shell_out_with_systems_locale, #shell_out_with_systems_locale!

Methods included from Mixin::PathSanity

#enforce_path_sanity, #sanitized_path

Constructor Details

#initialize(repo_path, ui, opts = {}) ⇒ CookbookSCMRepo

Returns a new instance of CookbookSCMRepo


34
35
36
37
38
39
40
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 34

def initialize(repo_path, ui, opts = {})
  @repo_path = repo_path
  @ui = ui
  @default_branch = "master"
  @use_current_branch = false
  apply_opts(opts)
end

Instance Attribute Details

#default_branchObject (readonly)

Returns the value of attribute default_branch


30
31
32
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 30

def default_branch
  @default_branch
end

#repo_pathObject (readonly)

Returns the value of attribute repo_path


29
30
31
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 29

def repo_path
  @repo_path
end

#uiObject (readonly)

Returns the value of attribute ui


32
33
34
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 32

def ui
  @ui
end

#use_current_branchObject (readonly)

Returns the value of attribute use_current_branch


31
32
33
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 31

def use_current_branch
  @use_current_branch
end

Instance Method Details

#branch_exists?(branch_name) ⇒ Boolean

Returns:

  • (Boolean)

121
122
123
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 121

def branch_exists?(branch_name)
  git("branch --no-color").stdout.lines.any? { |l| l =~ /\s#{Regexp.escape(branch_name)}(?:\s|$)/ }
end

#finalize_updates_to(cookbook_name, version) ⇒ Object


88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 88

def finalize_updates_to(cookbook_name, version)
  if update_count = updated?(cookbook_name)
    ui.info "#{update_count} files updated, committing changes"
    git("add #{cookbook_name}")
    git("commit -m \"Import #{cookbook_name} version #{version}\" -- #{cookbook_name}")
    ui.info("Creating tag cookbook-site-imported-#{cookbook_name}-#{version}")
    git("tag -f cookbook-site-imported-#{cookbook_name}-#{version}")
    true
  else
    ui.info("No changes made to #{cookbook_name}")
    false
  end
end

#get_current_branchObject


125
126
127
128
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 125

def get_current_branch
  ref = git("symbolic-ref HEAD").stdout
  ref.chomp.split("/")[2]
end

#merge_updates_from(cookbook_name, version) ⇒ Object


102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 102

def merge_updates_from(cookbook_name, version)
  branch = "chef-vendor-#{cookbook_name}"
  Dir.chdir(repo_path) do
    if system("git merge #{branch}")
      ui.info("Cookbook #{cookbook_name} version #{version} successfully installed")
    else
      ui.error("You have merge conflicts - please resolve manually")
      ui.info("Merge status (cd #{repo_path}; git status):")
      system("git status")
      exit 3
    end
  end
end

#prepare_to_import(cookbook_name) ⇒ Object


77
78
79
80
81
82
83
84
85
86
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 77

def prepare_to_import(cookbook_name)
  branch = "chef-vendor-#{cookbook_name}"
  if branch_exists?(branch)
    ui.info("Pristine copy branch (#{branch}) exists, switching to it.")
    git("checkout #{branch}")
  else
    ui.info("Creating pristine copy branch #{branch}")
    git("checkout -b #{branch}")
  end
end

#reset_to_default_stateObject


72
73
74
75
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 72

def reset_to_default_state
  ui.info("Checking out the #{default_branch} branch.")
  git("checkout #{default_branch}")
end

#sanity_checkObject


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
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 42

def sanity_check
  unless ::File.directory?(repo_path)
    ui.error("The cookbook repo path #{repo_path} does not exist or is not a directory")
    exit 1
  end
  unless git_repo?(repo_path)
    ui.error "The cookbook repo #{repo_path} is not a git repository."
    ui.info("Use `git init` to initialize a git repo")
    exit 1
  end
  if use_current_branch
    @default_branch = get_current_branch()
  end
  unless branch_exists?(default_branch)
    ui.error "The default branch '#{default_branch}' does not exist"
    ui.info "If this is a new git repo, make sure you have at least one commit before installing cookbooks"
    exit 1
  end
  cmd = git("status --porcelain")
  if cmd.stdout =~ DIRTY_REPO
    ui.error "You have uncommitted changes to your cookbook repo (#{repo_path}):"
    ui.msg cmd.stdout
    ui.info "Commit or stash your changes before importing cookbooks"
    exit 1
  end
  # TODO: any untracked files in the cookbook directory will get nuked later
  # make this an error condition also.
  true
end

#updated?(cookbook_name) ⇒ Boolean

Returns:

  • (Boolean)

116
117
118
119
# File 'lib/chef/knife/core/cookbook_scm_repo.rb', line 116

def updated?(cookbook_name)
  update_count = git("status --porcelain -- #{cookbook_name}").stdout.strip.lines.count
  update_count == 0 ? nil : update_count
end