Class: Codger::Manager

Inherits:
Object
  • Object
show all
Defined in:
lib/codger/manager.rb

Overview

Responsible for:

  • Reading, writing, and to some degree interpreting configuration files.

  • Looking up code generators from their identifiers.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Manager

Create an instance with project-level settings stored at the specified path (does not need to exist yet, and will not be created unless necessary).



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/codger/manager.rb', line 25

def initialize(path)
  @project_path = path
  @project_settings = {
    runs: []
  }.with_indifferent_access
  if File.exists?(@project_path)
    @project_settings.merge! YAML.load(File.read(@project_path))
  end

  @global_settings = {
    config: {
      diff: 'diff -ur %SOURCE %DEST'
    },
    cached: {}
  }.with_indifferent_access
  if File.exists?(globals_path)
    @global_settings.merge! YAML.load(File.read(globals_path))
  end
end

Instance Attribute Details

#global_settingsObject (readonly)

The global settings map (i.e. from ~/.codger/codger.yaml)



19
20
21
# File 'lib/codger/manager.rb', line 19

def global_settings
  @global_settings
end

#project_settingsObject (readonly)

The project settings map (i.e. from .codger)



21
22
23
# File 'lib/codger/manager.rb', line 21

def project_settings
  @project_settings
end

Class Method Details

.defaultObject

Return an instance using any settings in the .codger file (if one exists) of the working directory.



13
14
15
# File 'lib/codger/manager.rb', line 13

def default
  @config ||= Manager.new(File.join(Dir.pwd, '.codger'))
end

Instance Method Details

#cache(identifier) ⇒ Object

Clone the specified repo into #cached_base.



86
87
88
89
90
91
92
93
94
95
# File 'lib/codger/manager.rb', line 86

def cache identifier
  return if settings[:cached][identifier]
  identifier = File.expand_path identifier if File.exist?(identifier) # hacky
  FileUtils.mkdir_p cached_base
  next_id = Dir.entries(cached_base).map(&:to_i).max + 1
  clone = File.join cached_base, next_id.to_s
  Git.clone identifier, clone
  @global_settings[:cached][identifier] = clone
  save_globals
end

#cached_baseObject

Return the folder where clones can be saved - ‘cached’ in #codger_home.



142
143
144
# File 'lib/codger/manager.rb', line 142

def cached_base
  File.join codger_home, 'cached'
end

#codger_homeObject

Return the folder where global settings and other resources can be saved. By default ~/.codger but this can be overridden using ‘codger_home’ in #project_settings.



132
133
134
# File 'lib/codger/manager.rb', line 132

def codger_home
  @project_settings[:codger_home] || File.join(Dir.home, '.codger')
end

#diff_command(source, dest) ⇒ Object

Return the command to use for diffing two folders.



152
153
154
# File 'lib/codger/manager.rb', line 152

def diff_command(source, dest)
  settings[:config][:diff].gsub('%SOURCE', source).gsub('%DEST', dest)
end

#generator(id) ⇒ Object

Creates a Generator, currently always a Skeleton. id can be:

  • a filesystem path, which will be used directly

  • a git uri, which will be cloned to a temporary directory

  • a substring of the identifier of a cached skeleton



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/codger/manager.rb', line 50

def generator(id)
  if File.exists? id
    clone = id
    id = File.expand_path id
  elsif cached = match_cached_identifier(id)
    id, clone = cached
    git = Git.open(clone)
    # https://github.com/schacon/ruby-git/issues/32
    begin
      git.lib.send(:command, 'pull')
    rescue StandardError => ex
      puts "Warning: could not update cached clone: #{ex.inspect}"
    end
  else
    clone = Dir.mktmpdir
    Git.clone id, clone
    at_exit do
      raise "I'm scared to delete #{clone}" unless clone.size > 10 # just being paranoid before rm_rf'ing
      FileUtils.rm_rf clone
    end
  end
  Skeleton.new clone, id
end

#globals_pathObject

Return the file where global settings should be saved - ‘codger.yaml’ in #codger_home.



137
138
139
# File 'lib/codger/manager.rb', line 137

def globals_path
  File.join(codger_home, 'codger.yaml')
end

#match_cached_identifier(identifier) ⇒ Object

Find a cached repository with an identifier similar to the given one (specifically, that has the given one as a substring). Returns [identifier, clone]



112
113
114
115
116
117
# File 'lib/codger/manager.rb', line 112

def match_cached_identifier identifier
  return nil if identifier.size < 4 # crude typo protection
  settings[:cached].detect do |cached_id, clone|
    cached_id.include?(identifier)
  end
end

#record_run(generator) ⇒ Object

Saves the tags, identifier, and params from the last run of the given generator instance in the project settings file.



76
77
78
79
80
81
82
83
# File 'lib/codger/manager.rb', line 76

def record_run(generator)
  @project_settings[:runs] << {
    tags: [generator.name] + generator.tags,
    generator: generator.identifier,
    params: generator.params
  }.with_indifferent_access
  save_project
end

#save_globalsObject

Save #global_settings.



125
126
127
128
# File 'lib/codger/manager.rb', line 125

def save_globals
  FileUtils.mkdir_p codger_home
  File.write globals_path, @global_settings.to_yaml
end

#save_projectObject

Save #project_settings.



120
121
122
# File 'lib/codger/manager.rb', line 120

def save_project
  File.write @project_path, @project_settings.to_yaml
end

#settingsObject

Return a merged map of #global_settings and #project_settings.



147
148
149
# File 'lib/codger/manager.rb', line 147

def settings
  @global_settings.deep_merge @project_settings
end

#uncache(identifier) ⇒ Object

Remove the specified repo from #cached_base. identifier may be a substring of the desired repo.



99
100
101
102
103
104
105
106
107
# File 'lib/codger/manager.rb', line 99

def uncache identifier
  if match = match_cached_identifier(identifier)
    @global_settings[:cached].delete match[0]
    clone = match[1]
    raise "I'm scared to delete #{clone}" unless clone.size > 10 && clone.start_with?(cached_base) # again, paranoia
    FileUtils.rm_rf clone
    save_globals
  end
end