all repos — dotfiles @ 5befc6d337936a186587925eb7d7e93f78956d55

my *nix dotfiles

bin/git-vanity-sha (view raw)

 1#!/usr/bin/env ruby
 2require 'digest'
 3
 4module VanitySha
 5  extend self
 6
 7  COMMITTER_PATTERN = /^committer .* \<.*\> (?<timestamp>\d+)(?<timezone>.*$)/
 8
 9  TIMESTAMP_DELTA_MAX = 10 * 24 * 60 * 60
10
11  DELTAS = Enumerator.new do |enumerator|
12    for i in 0..TIMESTAMP_DELTA_MAX
13      enumerator << i
14      enumerator << -i
15    end
16  end
17
18  def get_commit_info()
19    `git cat-file commit HEAD`
20  end
21
22  def extract_committer(commit_info)
23    committer = commit_info
24    .split("\n")
25    .map {|line| line.match(COMMITTER_PATTERN)}
26    .compact
27    .first
28
29    [committer.string, committer[:timestamp].to_i, committer[:timezone]]
30  end
31
32  def search(commit_info, hex_prefix)
33    committer_line, commit_ts = extract_committer(commit_info)
34
35    DELTAS.each do |delta|
36      new_committer_line = committer_line.sub(commit_ts.to_s, (commit_ts + delta).to_s)
37      new_commit = commit_info.sub(committer_line, new_committer_line)
38      new_sha = get_sha(new_commit)
39      return [delta, new_sha] if new_sha.start_with?(hex_prefix)
40    end
41    nil
42  end
43
44  def get_sha(commit_info)
45    Digest::SHA1.hexdigest "#{commit_header(commit_info)}#{commit_info}"
46  end
47
48  def amend_commit(new_ts, original_tz)
49    `LC_ALL=C GIT_COMMITTER_DATE=\"#{new_ts}#{original_tz}\" git commit --amend --no-edit`
50  end
51
52  def commit_header(commit_info)
53    "commit #{commit_info.length}\0"
54  end
55end
56
57if ARGV.length != 1 || ARGV[0].length < 1
58  puts "usage: git vanity-sha prefix"
59  puts "example: git vanity-sha CAFE"
60  exit(1)
61end
62
63target_prefix = ARGV[0].downcase
64original_commit_info = VanitySha.get_commit_info()
65_, original_ts, original_tz = VanitySha.extract_committer(original_commit_info)
66
67puts "Searching for new SHA...\n"
68
69result = VanitySha.search(original_commit_info, target_prefix)
70
71if result
72  delta, sha = result
73  new_ts = original_ts + delta
74
75  puts "SHA found: #{sha.sub(target_prefix, "\e[32m#{target_prefix}\e[0m")}"
76  puts "Change committer timestamp to #{Time.at(new_ts)}? This will amend your commit."
77  print "(y/n): "
78
79  if STDIN.gets.chomp == "y"
80    VanitySha.amend_commit(new_ts, original_tz)
81    puts "\n" + "-" * 47
82    puts `git show --quiet --format=short HEAD`
83  else
84    puts "Aborting."
85  end
86else
87  puts "Failed to generate a sha with prefix #{target_prefix}."
88end
89