Class: Gjp::Git

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/gjp/git.rb

Overview

facade to git, currently implemented with calls to the git command prefixes all tags with “gjp_”

Instance Method Summary collapse

Methods included from Logging

#log

Constructor Details

#initialize(directory) ⇒ Git

inits a new git manager object pointing to the specified directory



11
12
13
# File 'lib/gjp/git.rb', line 11

def initialize(directory)
  @directory = directory
end

Instance Method Details

#changed_files_between(start_tag, end_tag, directory) ⇒ Object

returns a list of filenames that changed in the repo between specified tags, in a certain directory



34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/gjp/git.rb', line 34

def changed_files_between(start_tag, end_tag, directory)
  Dir.chdir(@directory) do
    prefixed_start_tag = "gjp_#{start_tag}"
    prefixed_end_tag = (
      if end_tag
        "gjp_#{end_tag}"
      else
        "HEAD"
      end
    )
    `git diff-tree --no-commit-id --name-only -r #{prefixed_start_tag} #{prefixed_end_tag} -- #{directory}`
      .split("\n")
  end
end

#changed_files_since(tag) ⇒ Object

returns a list of filenames that changed in the repo since the specified tag



28
29
30
# File 'lib/gjp/git.rb', line 28

def changed_files_since(tag)
  changed_files_between(tag, nil, ".")
end

#commit_whole_directory(message, tag = nil, tag_message = nil) ⇒ Object

adds all files in the current directory and removes all files not in the current directory. if tag is given, commit is also tagged



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/gjp/git.rb', line 52

def commit_whole_directory(message, tag = nil, tag_message = nil)
  Dir.chdir(@directory) do
    log.debug "committing with message: #{message}"

    # rename all .gitignore files by default as
    # they prevent snapshotting
    Find.find(".") do |file|
      if file =~ /\.gitignore$/
        FileUtils.mv(file, "#{file}_disabled_by_gjp")
      end
    end

    `git rm -r --cached --ignore-unmatch .`
    `git add .`
    `git commit -m "#{message}"`

    unless tag.nil?
      if !tag_message.nil?
        `git tag gjp_#{tag} -m "#{tag_message}"`
      else
        `git tag gjp_#{tag}`
      end
    end
  end
end

#delete_tag(tag) ⇒ Object

deletes a tag



126
127
128
129
130
# File 'lib/gjp/git.rb', line 126

def delete_tag(tag)
  Dir.chdir(@directory) do
    `git tag -d gjp_#{tag}`
  end
end

#get_message(tag) ⇒ Object

returns the tag message



133
134
135
# File 'lib/gjp/git.rb', line 133

def get_message(tag)
  `git cat-file tag gjp_#{tag}`.split.last
end

#get_tag_maximum_suffix(prefix) ⇒ Object

returns the highest suffix found in tags with the given prefix



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/gjp/git.rb', line 79

def get_tag_maximum_suffix(prefix)
  Dir.chdir(@directory) do
    `git tag`.split.map do |tag|
      if tag =~ /^gjp_#{prefix}_([0-9]+)$/
        Regexp.last_match[1].to_i
      else
        0
      end
    end.max || 0
  end
end

#initObject

inits a repo



16
17
18
19
20
21
22
23
24
# File 'lib/gjp/git.rb', line 16

def init
  Dir.chdir(@directory) do
    if Dir.exist?(".git") == false
      `git init`
    else
      raise GitAlreadyInitedError
    end
  end
end

#merge_with_tag(path, new_path, tag) ⇒ Object

3-way merges the git file at path with the one in new_path assuming they have a common ancestor at the specified tag returns the conflict count



112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/gjp/git.rb', line 112

def merge_with_tag(path, new_path, tag)
  Dir.chdir(@directory) do
    log.debug "calling git show gjp_#{tag}:#{path} > #{path}.old_version, output follows"
    `git show gjp_#{tag}:#{path} > #{path}.old_version`
    log.debug "calling git merge-file #{path} #{path}.old_version #{new_path}, output follows"
    `git merge-file #{path} #{path}.old_version #{new_path} \
      -L "newly generated" -L "previously generated" -L "user edited"`
    conflict_count = $?.exitstatus
    File.delete "#{path}.old_version"
    return conflict_count
  end
end

#revert_whole_directory(path, tag) ⇒ Object

reverts path contents as per specified tag



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/gjp/git.rb', line 92

def revert_whole_directory(path, tag)
  Dir.chdir(@directory) do
    # reverts added and modified files, both in index and working tree
    `git checkout -f gjp_#{tag} -- #{path}`

    # compute the list of deleted files
    files_in_tag = `git ls-tree --name-only -r gjp_#{tag} -- #{path}`.split("\n")
    files_in_head = `git ls-tree --name-only -r HEAD -- #{path}`.split("\n")
    files_added_after_head = `git ls-files -o -- #{path}`.split("\n")
    files_to_delete = files_in_head - files_in_tag + files_added_after_head

    files_to_delete.each do |file|
      FileUtils.rm_rf(file)
    end
  end
end