├── acl ├── commit-msg ├── pre-rebase ├── pre-commit └── update └── fast-import.rb /acl/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | message_file = ARGV[0] 3 | message = File.read(message_file) 4 | 5 | $regex = /\[ref: (\d+)\]/ 6 | 7 | if !$regex.match(message) 8 | puts "[POLICY] Your message is not formatted correctly" 9 | exit 1 10 | end 11 | -------------------------------------------------------------------------------- /acl/pre-rebase: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | base_branch = ARGV[0] 4 | if ARGV[1] 5 | topic_branch = ARGV[1] 6 | else 7 | topic_branch = "HEAD" 8 | end 9 | 10 | target_shas = `git rev-list #{base_branch}..#{topic_branch}`.split("\n") 11 | remote_refs = `git branch -r`.split("\n").map { |r| r.strip } 12 | 13 | target_shas.each do |sha| 14 | remote_refs.each do |remote_ref| 15 | shas_pushed = `git rev-list ^#{sha}^@ refs/remotes/#{remote_ref}` 16 | if shas_pushed.split(“\n”).include?(sha) 17 | puts "[POLICY] Commit #{sha} has already been pushed to #{remote_ref}" 18 | exit 1 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /acl/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | $user = ENV['USER'] 4 | 5 | # [ insert acl_access_data method from above ] 6 | 7 | # only allows certain users to modify certain subdirectories in a project 8 | def check_directory_perms 9 | access = get_acl_access_data('.git/acl') 10 | 11 | files_modified = `git diff-index --cached --name-only HEAD`.split("\n") 12 | files_modified.each do |path| 13 | next if path.size == 0 14 | has_file_access = false 15 | access[$user].each do |access_path| 16 | if !access_path || (path.index(access_path) == 0) 17 | has_file_access = true 18 | end 19 | if !has_file_access 20 | puts "[POLICY] You do not have access to push to #{path}" 21 | exit 1 22 | end 23 | end 24 | end 25 | 26 | check_directory_perms 27 | -------------------------------------------------------------------------------- /fast-import.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | require 'digest/sha1' 3 | 4 | last_mark = nil 5 | $author = 'Scott Chacon ' 6 | 7 | $marks = [] 8 | def convert_dir_to_mark(dir) 9 | if !$marks.include?(dir) 10 | $marks << dir 11 | end 12 | ($marks.index(dir) + 1).to_s 13 | end 14 | 15 | def convert_dir_to_date(dir) 16 | if dir == 'current' 17 | return Time.now().to_i 18 | else 19 | dir = dir.gsub('back_', '') 20 | (year, month, day) = dir.split('_') 21 | return Time.local(year, month, day).to_i 22 | end 23 | end 24 | 25 | def export_data(string) 26 | print "data #{string.size}\n#{string}" 27 | end 28 | 29 | def inline_data(file, code = 'M', mode = '644') 30 | content = File.read(file) 31 | puts "#{code} #{mode} inline #{file}" 32 | export_data(content) 33 | end 34 | 35 | def print_export(dir, last_mark) 36 | mark = convert_dir_to_mark(dir) 37 | date = convert_dir_to_date(dir) 38 | 39 | # print the import information 40 | puts 'commit refs/heads/master' 41 | puts 'mark :' + mark 42 | puts "committer #{$author} #{date} -0700" 43 | export_data('imported from ' + dir) 44 | puts 'from :' + last_mark if last_mark 45 | 46 | puts 'deleteall' 47 | Dir.glob("**/*").each do |file| 48 | next if !File.file?(file) 49 | inline_data(file) 50 | end 51 | 52 | return mark 53 | end 54 | 55 | # loop through the directories 56 | Dir.chdir(ARGV[0]) do 57 | Dir.glob("*").each do |dir| 58 | next if File.file?(dir) 59 | 60 | # move into the target directory 61 | Dir.chdir(dir) do 62 | last_mark = print_export(dir, last_mark) 63 | end 64 | end 65 | end -------------------------------------------------------------------------------- /acl/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | $refname = ARGV[0] 4 | $oldrev = ARGV[1] 5 | $newrev = ARGV[2] 6 | $user = ENV['USER'] 7 | 8 | puts "Enforcing Policies... \n(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})" 9 | 10 | $regex = /\[ref: (\d+)\]/ 11 | 12 | # enforced custom commit message format 13 | def check_message_format 14 | missed_revs = `git rev-list #{$oldrev}..#{$newrev}`.split("\n") 15 | missed_revs.each do |rev| 16 | message = `git cat-file commit #{rev} | sed '1,/^$/d'` 17 | if !$regex.match(message) 18 | puts "[POLICY] Your message is not formatted correctly" 19 | exit 1 20 | end 21 | end 22 | end 23 | check_message_format 24 | 25 | def get_acl_access_data(acl_file) 26 | # read in ACL data 27 | acl_file = File.read(acl_file).split("\n").reject { |line| line == '' } 28 | access = {} 29 | acl_file.each do |line| 30 | avail, users, path = line.split('|') 31 | next unless avail == 'avail' 32 | users.split(',').each do |user| 33 | access[user] ||= [] 34 | access[user] << path 35 | end 36 | end 37 | access 38 | end 39 | 40 | # only allows certain users to modify certain subdirectories in a project 41 | def check_directory_perms 42 | access = get_acl_access_data('acl') 43 | 44 | # see if anyone is trying to push something they can't 45 | new_commits = `git rev-list #{$oldrev}..#{$newrev}`.split("\n") 46 | new_commits.each do |rev| 47 | files_modified = `git log -1 --name-only --pretty=format:'' #{rev}`.split("\n") 48 | files_modified.each do |path| 49 | next if path.size == 0 50 | has_file_access = false 51 | access[$user].each do |access_path| 52 | if !access_path || # user has access to everything 53 | (path.index(access_path) == 0) # access to this path 54 | has_file_access = true 55 | end 56 | end 57 | if !has_file_access 58 | puts "[POLICY] You do not have access to push to #{path}" 59 | exit 1 60 | end 61 | end 62 | end 63 | end 64 | check_directory_perms 65 | 66 | # enforces fast-forward only pushes 67 | def check_fast_forward 68 | missed_refs = `git rev-list #{$newrev}..#{$oldrev}` 69 | missed_ref_count = missed_refs.split("\n").size 70 | if missed_ref_count > 0 71 | puts "[POLICY] Cannot push a non fast-forward reference" 72 | exit 1 73 | end 74 | end 75 | check_fast_forward 76 | --------------------------------------------------------------------------------