Class: GitCommit
- Inherits:
-
Object
- Object
- GitCommit
- Defined in:
- lib/commit/git_commit.rb,
lib/commit/helper.rb,
lib/commit/options.rb
Overview
Originally written in bash by Mike Slinn 2005-09-05 Converted to Ruby and added MAX_SIZE 2024-12-11 See docs.github.com/en/repositories/working-with-files/managing-large-files/configuring-git-large-file-storage See docs.github.com/en/repositories/working-with-files/managing-large-files/about-large-files-on-github
Constant Summary collapse
- QUIET =
0- NORMAL =
1- VERBOSE =
2- ANNOYING =
3- STFU =
4
Instance Method Summary collapse
-
#add_recursively(name) ⇒ Object
Needs absolute path or the path relative to the current directory, not just the name of the directory.
- #commit_push(msg = '-') ⇒ Object
- #discover_branch ⇒ Object
-
#escape(string) ⇒ Object
Handles single quotes, spaces and square braces in the given string.
- #file_add(filename) ⇒ Object
- #git_project? ⇒ Boolean
- #help(msg = nil) ⇒ Object
-
#initialize(default_branch: 'master') ⇒ GitCommit
constructor
A new instance of GitCommit.
-
#large_file?(filename) ⇒ Boolean
Assumes .gitignore is never large.
- #large_files ⇒ Object
- #main ⇒ Object
- #needs_newline(filename) ⇒ Object
- #parse_options ⇒ Object
- #process_tag ⇒ Object
-
#recursive_add ⇒ Object
Exclude big files, git add all others.
- #run(command, verbose: true, do_not_execute: false) ⇒ Object
- #scan_directory(path) ⇒ Object
Constructor Details
#initialize(default_branch: 'master') ⇒ GitCommit
Returns a new instance of GitCommit.
27 28 29 30 31 32 |
# File 'lib/commit/git_commit.rb', line 27 def initialize(default_branch: 'master') @branch = default_branch @commit_size = 0 @gitignore_dirty = false @nh = ActiveSupport::NumberHelper end |
Instance Method Details
#add_recursively(name) ⇒ Object
Needs absolute path or the path relative to the current directory, not just the name of the directory
10 11 12 13 14 15 16 17 18 19 |
# File 'lib/commit/helper.rb', line 10 def add_recursively(name) Dir.entries(name).each do |entry| path = "#{name}/#{entry}" if File.directory(entry) scan_directory path else file_add path end end end |
#commit_push(msg = '-') ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/commit/git_commit.rb', line 34 def commit_push(msg = '-') puts msg.yellow if msg msg = [:commit_message] if [:commit_message] discover_branch puts "Committing with message '#{msg}'".green unless [:verbosity] == QUIET run "git commit -m '#{msg}' 2>&1 | sed -e '/^X11/d' -e '/^Warning:/d'", verbose: [:verbosity] >= VERBOSE # @repo.push 'origin', ['refs/heads/master'] # Needs a callback to handle authentication puts "Pushing to origin #{@branch}".green unless [:verbosity] == QUIET run "git push origin #{@branch} --tags 3>&1 1>&2 2>&3 | sed -e '/^X11/d' -e '/^Warning:/d'", verbose: [:verbosity] >= VERBOSE @change_count = 0 @commit_size = 0 end |
#discover_branch ⇒ Object
49 50 51 52 53 54 55 56 57 |
# File 'lib/commit/git_commit.rb', line 49 def discover_branch if @repo.branches.entries.empty? # puts "\nYour git repository is empty. Please add at least one file before committing.".red # exit 4 run "git branch -M #{@branch}" else @branch = @repo.head.name.sub(%r{^refs/heads/}, '') end end |
#escape(string) ⇒ Object
Handles single quotes, spaces and square braces in the given string
22 23 24 25 26 27 |
# File 'lib/commit/helper.rb', line 22 def escape(string) string.gsub("'", "\\\\'") .gsub(' ', '\\ ') .gsub('[', '\\[') .gsub(']', '\\]') end |
#file_add(filename) ⇒ Object
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 55 |
# File 'lib/commit/helper.rb', line 30 def file_add(filename) file_size = File.exist?(filename) ? File.size(filename) : 0 if large_file?(filename) msg = " Not adding '\#{filename}' because the git file size limit is \#{@nh.to_human MAX_SIZE},\n however the file is \#{@nh.to_human file_size}.\n The file will be added to .gitignore.\n MESSAGE\n puts msg.yellow unless @options[:verbosity] == QUIET\n\n newline = needs_newline('.gitignore') ? \"\\n\" : ''\n File.write('.gitignore', \"\#{newline}\#{filename}\\n\", mode: 'a')\n @gitignore_dirty = true\n elsif filename == '.gitignore'\n @gitignore_dirty = true\n else\n if @commit_size + file_size >= MAX_SIZE / 2.0\n # Defeat formatter\n commit_push 'A portion of the files to be committed is being pushed now because they are large.'\n end\n puts \"Adding '\#{escape filename}'\".green unless @options[:verbosity] == QUIET\n run ['git', 'add', escape(filename)], verbose: @options[:verbosity] >= VERBOSE\n end\n @change_count += 1\n @commit_size += file_size\nend\n" |
#git_project? ⇒ Boolean
59 60 61 |
# File 'lib/commit/git_commit.rb', line 59 def git_project? run 'git rev-parse 2> /dev/null', verbose: false end |
#help(msg = nil) ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/commit/options.rb', line 5 def help(msg = nil) printf "Error: #{msg}\n\n".yellow unless msg.nil? msg = " commit v\#{Commit::VERSION}\n\n Runs git commit without prompting for a message.\n Files larger than \#{@nh.to_human MAX_SIZE} are added to .gitignore instead of being committed.\n\n Usage: commit [options]\n Where options are:\n -a \"tag message\"\n -m \"commit message\"\n -v 0 # Minimum verbosity\n -v 1 # Default verbosity\n -v 2 # Maximum verbosity\n\n Examples:\n commit # The default commit message is just a single dash (-)\n commit -v 0\n commit -m \"This is a commit message\"\n commit -v 0 -m \"This is a commit message\"\n commit -a 0.1.2\n\n This gem is further described in https://mslinn.com/git/1050-commit.html\n HELP\n puts msg.yellow\n exit 1\nend\n" |
#large_file?(filename) ⇒ Boolean
Assumes .gitignore is never large
58 59 60 |
# File 'lib/commit/helper.rb', line 58 def large_file?(filename) File.size(filename) > MAX_SIZE if File.exist?(filename) end |
#large_files ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/commit/git_commit.rb', line 63 def large_files large = [] @repo.status do |path, flags| puts "#{path} #{flags}" if [:verbosity] >= NORMAL if File(path).dir? scan_dir path elsif large_file?(filename) large << path.gsub(' ', '\ ').gsub('[', '\[').gsub(']', '\]') end end large end |
#main ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/commit/git_commit.rb', line 76 def main = repo_dir = ARGV.empty? ? Dir.pwd : ARGV[0] Dir.chdir(repo_dir) unless ARGV.empty? if git_project? process_tag # Exits if a tag was created @repo = Rugged::Repository.new repo_dir recursive_add commit_push if @commit_size.positive? else puts "Error: '#{repo_dir}' does not contain a git project".red exit 3 end end |
#needs_newline(filename) ⇒ Object
62 63 64 65 66 67 |
# File 'lib/commit/helper.rb', line 62 def needs_newline(filename) return false unless File.exist? filename file_contents = File.read filename file_contents.nil? || file_contents.empty? || !file_contents.end_with?("\n") end |
#parse_options ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/commit/options.rb', line 34 def = { message: '-', verbosity: 1 } OptionParser.new do |parser| parser.program_name = File.basename __FILE__ @parser = parser parser.on('-a', '--tag TAG_MESSAGE', 'Specify tag message') parser.on('-m', '--message COMMIT_MESSAGE', 'Specify commit message') parser.on('-v', '--verbosity VERBOSITY', Integer, 'Verbosity (0..2)') parser.on_tail('-h', '--help', 'Show this message') do help end end.order!(into: ) help "Invalid verbosity value (#{options[:verbosity]})." if [:verbosity].negative? || [:verbosity] > 2 if ARGV.length > 1 help " Incorrect syntax.\n After removing the options, the remaining command line was:\n \#{ARGV.join ' '}\n END_MSG\n end\n options\nend\n" |
#process_tag ⇒ Object
91 92 93 94 95 96 97 98 |
# File 'lib/commit/git_commit.rb', line 91 def process_tag tag = [:tag] return unless tag run "git tag -a #{tag} -m 'v#{tag}'", verbose: [:verbosity] >= VERBOSE run 'git push origin --tags', verbose: [:verbosity] >= VERBOSE exit end |
#recursive_add ⇒ Object
Exclude big files, git add all others
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/commit/helper.rb', line 77 def recursive_add @change_count = 0 run ['git', 'add', '--all'], verbose: [:verbosity] >= VERBOSE @repo.status do |path, flags| next if flags.include? :ignored if File.directory? path scan_directory path else file_add path end end if @gitignore_dirty puts 'Changing .gitignore'.green unless [:verbosity] == QUIET run 'git add .gitignore', verbose: [:verbosity] >= 2 @change_count += 1 end return unless @change_count.zero? puts 'No changes were detected to this git repository.'.green if [:verbosity] >= VERBOSE exit end |
#run(command, verbose: true, do_not_execute: false) ⇒ Object
101 102 103 104 105 106 107 108 109 |
# File 'lib/commit/git_commit.rb', line 101 def run(command, verbose: true, do_not_execute: false) if command.instance_of?(Array) puts command.join(' ') if verbose Kernel.system(*command) unless do_not_execute else puts command if verbose `#{command}`.chomp unless do_not_execute end end |
#scan_directory(path) ⇒ Object
100 101 102 103 104 105 106 107 108 109 |
# File 'lib/commit/helper.rb', line 100 def scan_directory(path) Dir.children(path) do |name| child_path = "#{path}/#{name}" if File.directory? child_path scan_directory child_path else file_add child_path end end end |