Class: GitCleaner

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

Constant Summary collapse

CONFIG_FILE =
'.git_cleaner'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeGitCleaner

Returns a new instance of GitCleaner.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/git_cleaner.rb', line 11

def initialize
  if File.exist?("./#{CONFIG_FILE}")
    @config = YAML.load_file("./#{CONFIG_FILE}")
    
    if @config['lighthouse']
      Lighthouse.token    = @config['lighthouse']['token']
      Lighthouse.  = @config['lighthouse']['account']
      self.project_name   = @config['lighthouse']['project']
    end
  else
    # We might want to warn here if there's no config file at all. Right now it's not a big deal.
  end
  
  @options = {:rules => {}}
  
  OptionParser.new do |opts|
    opts.banner = "Usage: git_cleanup --remote"

    opts.on('-r', '--remote', 'Clean up remote branches') do |f|
      @options[:mode] = 'remote'
    end

    opts.on('-l', '--local', 'Clean up local branches') do
      @options[:mode] = 'local'
    end
    
    opts.on('-t', '--test', 'Test mode - no changes will be made') do
      @options[:test_mode] = true
    end
    
    opts.on('-b', '--before date', 'Automatically delete branches last updated before') do |date|
      @options[:rules].merge!(:before => eval(date))
    end
    
    opts.on('-s', '--state ticket_state', 'Automatically delete branches corresponding to a Lighthouse ticket state') do |state|
      puts "#{CONFIG_FILE} with Lighthouse token, account, and project are required to match on ticket state" and exit unless Lighthouse.token && Lighthouse. && project_name
      @options[:rules].merge!(:state => state)
    end
    
    opts.on('-m', '--matching string', 'Automatically delete branches with names matching the string') do |string|
      @options[:rules].merge!(:matching => string)
    end
  end.parse!
end

Instance Attribute Details

#project_nameObject

Returns the value of attribute project_name.



9
10
11
# File 'lib/git_cleaner.rb', line 9

def project_name
  @project_name
end

Instance Method Details

#branch_modified(branch_info, format = :time_ago_in_words) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/git_cleaner.rb', line 96

def branch_modified(branch_info, format = :time_ago_in_words)      
  format_string =
    case format
    when :time_ago_in_words
      "%ar"
    when :absolute
      "%aD"
    end
    
  `git show --pretty=format:#{format_string} #{branch_info.string}`.split("\n")[0]
end

#cleanupObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/git_cleaner.rb', line 169

def cleanup
  branches = `git branch -a`.split.reject { |name| name == "*" }

  local_branches = branches.select do |branch|
    !(branch =~ /^remotes\/origin/)
  end

  remote_branches = branches.select do |branch|
    !local_branches.include?(branch)
  end

  local_or_remote = @options[:mode]

  if local_or_remote == 'local'
    prune_these(local_or_remote, local_branches)
  else
    prune_these(local_or_remote, remote_branches)
  end
end

#delete_local(branch_info) ⇒ Object



126
127
128
# File 'lib/git_cleaner.rb', line 126

def delete_local(branch_info)
  execute "git branch -D #{branch_info.string}"
end

#delete_remote(branch_info) ⇒ Object



130
131
132
133
# File 'lib/git_cleaner.rb', line 130

def delete_remote(branch_info)
  branch_info.string.gsub!(/(remotes\/)|(origin\/)/, '')
  execute "git push origin :#{branch_info.string}", "git remote prune origin"
end

#execute(*instructions) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/git_cleaner.rb', line 135

def execute(*instructions)
  if test_mode?
    puts "Test mode - The following instructions would be executed"
    
    instructions.each do |instruction|
      puts instruction
    end
  else
    instructions.each do |instruction|
      system instruction
    end
  end
end

#get_lighthouse_status(branch_info, project) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/git_cleaner.rb', line 149

def get_lighthouse_status(branch_info, project)
  lighthouse_id = 
    (matches = branch_info.string.match(/(^|\/)(\d+)-/)) ? matches[2] : nil

  if lighthouse_id
    tickets = project.tickets :q => lighthouse_id
    ticket  = tickets.first
    
    if ticket
      branch_info.lighthouse_state = ticket.state
      branch_info.lighthouse_message = "Lighthouse Info:\nTicket ##{lighthouse_id} state - #{ticket.state}"
      return
    end
  end
  
  branch_info.lighthouse_message = "No Lighthouse Info."
rescue StandardError => e
  puts "Unable to connect to Lighthouse"
end

#get_project(name) ⇒ Object



56
57
58
59
# File 'lib/git_cleaner.rb', line 56

def get_project(name)
  projects = Lighthouse::Project.find(:all)
  project  = projects.find {|pr| pr.name == name}
end

#match_before(branch_info, date) ⇒ Object

git_cleanup –before 1.month.ago



109
110
111
112
113
114
# File 'lib/git_cleaner.rb', line 109

def match_before(branch_info, date)
  last_updated = Time.parse(branch_modified(branch_info, :absolute))
  last_updated < date
rescue
  false
end

#match_matching(branch_info, string) ⇒ Object

git_cleanup –matching hotfix



122
123
124
# File 'lib/git_cleaner.rb', line 122

def match_matching(branch_info, string)
  branch_info.string =~ /#{string}/
end

#match_state(branch_info, state) ⇒ Object

git_cleanup –state resolved



117
118
119
# File 'lib/git_cleaner.rb', line 117

def match_state(branch_info, state)
  branch_info.lighthouse_state == state
end

#prune_these(local_or_remote, branches) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/git_cleaner.rb', line 61

def prune_these(local_or_remote, branches)
  project = get_project(project_name)

  branches.each do |branch|
    branch_info = OpenStruct.new(:string => branch, :local_or_remote => local_or_remote)
    
    puts "#{branch_info.string} (updated #{branch_modified(branch_info, :time_ago_in_words)})"

    if project
      get_lighthouse_status(branch_info, project)
      puts branch_info.lighthouse_message
    end
    
    if @options[:rules].empty?
      print "keep [return], delete [d]: "
      user_input = gets
      user_input.strip!

      case user_input
      when 'd'
        send "delete_#{local_or_remote}", branch_info
      end

      puts "\n"
    else
      rules_matched = @options[:rules].map do |rule_name, rule_body|
        send "match_#{rule_name}", branch_info, rule_body
      end

      send "delete_#{local_or_remote}", branch_info if rules_matched.all?
      puts "\n"
    end
  end
end

#test_mode?Boolean

Returns:

  • (Boolean)


189
190
191
# File 'lib/git_cleaner.rb', line 189

def test_mode?
  @options[:test_mode]
end