class Leg::Representations::Git
Public Instance Methods
checkout!(step_number)
click to toggle source
# File lib/leg/representations/git.rb, line 153 def checkout!(step_number) each_step do |cur_step, commit| if cur_step == step_number FileUtils.cd(repo_path) { `git checkout #{commit.oid} 2>/dev/null` } save_state(load_state.step!(step_number)) copy_repo_to_step! return true end end end
commit!(options = {})
click to toggle source
# File lib/leg/representations/git.rb, line 164 def commit!(options = {}) copy_step_to_repo! remaining_commits = repo.branches["master"] ? commits(after: repo.head.target.oid).map(&:oid) : [] FileUtils.cd(repo_path) do `git add -A` cmd = ["git", "commit", "-q"] cmd << "--amend" if options[:amend] cmd << "-m" << options[:message] if options[:message] cmd << "--no-edit" if options[:use_default_message] && options[:amend] cmd << "-m" << "Untitled step" if options[:use_default_message] && !options[:amend] system(*cmd) end if options[:amend] save_state(load_state.amend!) else save_state(load_state.add_commit!) end if options[:no_rebase] save_remaining_commits(remaining_commits) true else rebase!(remaining_commits) end end
copy_repo_to_step!()
click to toggle source
# File lib/leg/representations/git.rb, line 70 def copy_repo_to_step! FileUtils.mkdir_p(step_path) FileUtils.rm_rf(File.join(step_path, "."), secure: true) FileUtils.cd(repo_path) do files = Dir.glob("*", File::FNM_DOTMATCH) - [".", "..", ".git"] files.each do |f| FileUtils.cp_r(f, File.join(step_path, f)) end end end
copy_step_to_repo!()
click to toggle source
# File lib/leg/representations/git.rb, line 81 def copy_step_to_repo! FileUtils.mv( File.join(repo_path, ".git"), File.join(repo_path, "../.gittemp") ) FileUtils.rm_rf(File.join(repo_path, "."), secure: true) FileUtils.mv( File.join(repo_path, "../.gittemp"), File.join(repo_path, ".git") ) FileUtils.cd(step_path) do files = Dir.glob("*", File::FNM_DOTMATCH) - [".", ".."] files.each do |f| FileUtils.cp_r(f, File.join(repo_path, f)) end end end
each_commit(options = {}) { |commit| ... }
click to toggle source
# File lib/leg/representations/git.rb, line 107 def each_commit(options = {}) walker = Rugged::Walker.new(repo) walker.sorting(Rugged::SORT_TOPO | Rugged::SORT_REVERSE) master_commit = repo.branches["master"].target walker.push(master_commit) return [] if master_commit.oid == options[:after] walker.hide(options[:after]) if options[:after] return walker.to_a if not block_given? walker.each do |commit| yield commit end end
Also aliased as: commits
each_step(git_diff_options = {}) { |nil, commit, summary, text, patches| ... }
click to toggle source
# File lib/leg/representations/git.rb, line 126 def each_step(git_diff_options = {}) empty_tree = Rugged::Tree.empty(repo) step_num = 1 each_commit do |commit| commit_message = commit.message.strip summary = commit_message.lines.first.strip text = (commit_message.lines[2..-1] || []).join.strip next if commit_message == "-" commit_message = "" if commit_message == "~" last_commit = commit.parents.first diff = (last_commit || empty_tree).diff(commit, git_diff_options) patches = diff.each_patch.to_a if patches.empty? yield nil, commit, summary, text, patches else yield step_num, commit, summary, text, patches step_num += 1 end end end
init!()
click to toggle source
# File lib/leg/representations/git.rb, line 148 def init! FileUtils.mkdir_p(repo_path) FileUtils.cd(repo_path) { `git init` } end
load!(options = {}) { |step_num| ... }
click to toggle source
Options:
full_diffs: If true, diffs contain the entire file in one hunk instead of multiple contextual hunks. diffs_ignore_whitespace: If true, diffs don't show changes to lines when only the amount of whitespace is changed.
# File lib/leg/representations/git.rb, line 39 def load!(options = {}) git_diff_options = {} git_diff_options[:context_lines] = 100_000 if options[:full_diffs] git_diff_options[:ignore_whitespace_change] = true if options[:diffs_ignore_whitespace] page = nil tutorial = Leg::Tutorial.new(@config) each_step(git_diff_options) do |step_num, commit, summary, text, patches| if patches.empty? if summary =~ /^~~~ (.+)$/ tutorial << page unless page.nil? page = Leg::Page.new($1) page.footer_text = text unless text.empty? else puts "Warning: ignoring empty commit." end else patch = patches.map(&:to_s).join("\n") step_diffs = Leg::Diff.parse(patch) page ||= Leg::Page.new page << Leg::Step.new(step_num, summary, text, step_diffs) yield step_num if block_given? end end tutorial << page unless page.nil? tutorial end
rebase!(remaining_commits)
click to toggle source
# File lib/leg/representations/git.rb, line 203 def rebase!(remaining_commits) FileUtils.cd(repo_path) do remaining_commits.each.with_index do |commit, commit_idx| `git cherry-pick --allow-empty --allow-empty-message --keep-redundant-commits #{commit} 2>/dev/null` if not $?.success? copy_repo_to_step! save_remaining_commits(remaining_commits[(commit_idx+1)..-1]) save_state(load_state.conflict!) return false end end end save_remaining_commits(nil) save_state(nil) repo.references.update(repo.branches["master"], repo.head.target_id) repo.head = "refs/heads/master" copy_repo_to_step! true end
rebase_remaining!()
click to toggle source
# File lib/leg/representations/git.rb, line 199 def rebase_remaining! rebase!(load_remaining_commits) end
repo()
click to toggle source
# File lib/leg/representations/git.rb, line 103 def repo @repo ||= Rugged::Repository.new(repo_path) end
repo_path()
click to toggle source
# File lib/leg/representations/git.rb, line 99 def repo_path File.join(@config.path, ".leg/repo") end
reset!()
click to toggle source
# File lib/leg/representations/git.rb, line 228 def reset! save_state(nil) save_remaining_commits(nil) FileUtils.cd(repo_path) do `git cherry-pick --abort 2>/dev/null` end repo.head = "refs/heads/master" repo.checkout_head(strategy: :force) copy_repo_to_step! end
resolve!()
click to toggle source
# File lib/leg/representations/git.rb, line 190 def resolve! copy_step_to_repo! FileUtils.cd(repo_path) do `git add -A` `git -c core.editor=true cherry-pick --allow-empty --allow-empty-message --keep-redundant-commits --continue 2>/dev/null` end rebase!(load_remaining_commits) end
save!(tutorial, options = {}) { |step_num| ... }
click to toggle source
# File lib/leg/representations/git.rb, line 4 def save!(tutorial, options = {}) FileUtils.rm_rf(repo_path) FileUtils.mkdir_p(repo_path) FileUtils.cd(repo_path) do repo = Rugged::Repository.init_at(".") step_num = 1 tutorial.pages.each do |page| message = "~~~ #{page.filename}" message << "\n\n#{page.footer_text}" if page.footer_text add_commit(repo, nil, message, step_num) page.steps.each do |step| message = "#{step.summary}\n\n#{step.text}".strip add_commit(repo, step.to_patch, message, step_num) yield step_num if block_given? step_num += 1 end end #if options[:extra_path] # FileUtils.cp_r(File.join(options[:extra_path], "."), ".") # add_commit(repo, nil, "-", step_num, counter) #end repo.checkout_head(strategy: :force) if repo.branches["master"] end end
state()
click to toggle source
# File lib/leg/representations/git.rb, line 239 def state load_state end
Private Instance Methods
add_commit(repo, diff, message, step_num)
click to toggle source
# File lib/leg/representations/git.rb, line 300 def add_commit(repo, diff, message, step_num) message ||= "~" message.strip! message = "~" if message.empty? if diff stdin = IO.popen("git apply -", "w") stdin.write diff stdin.close end index = repo.index index.read_tree(repo.head.target.tree) unless repo.empty? Dir["**/*"].each do |path| unless File.directory?(path) oid = repo.write(File.read(path), :blob) index.add(path: path, oid: oid, mode: 0100644) end end options = {} options[:tree] = index.write_tree(repo) if @config.options[:repo_author_name] options[:author] = { name: @config.options[:repo_author_name], email: @config.options[:repo_author_email], time: Time.now } options[:committer] = options[:author] end options[:message] = message options[:parents] = repo.empty? ? [] : [repo.head.target] options[:update_ref] = "HEAD" commit_oid = Rugged::Commit.create(repo, options) if diff repo.references.create("refs/tags/step-#{step_num}", commit_oid) end end
load_remaining_commits()
click to toggle source
# File lib/leg/representations/git.rb, line 284 def load_remaining_commits if File.exist?(remaining_commits_path) File.readlines(remaining_commits_path).map(&:strip).reject(&:empty?) else [] end end
load_state()
click to toggle source
# File lib/leg/representations/git.rb, line 266 def load_state @state ||= if File.exist?(state_path) YAML.load_file(state_path) else State.new end end
modified_at()
click to toggle source
# File lib/leg/representations/git.rb, line 253 def modified_at if File.exist? repo_path repo = Rugged::Repository.new(repo_path) if master = repo.branches["master"] master.target.time end end end
remaining_commits_path()
click to toggle source
# File lib/leg/representations/git.rb, line 249 def remaining_commits_path File.join(@config.path, ".leg/remaining_commits") end
save_remaining_commits(remaining_commits)
click to toggle source
# File lib/leg/representations/git.rb, line 292 def save_remaining_commits(remaining_commits) if remaining_commits && !remaining_commits.empty? File.write(remaining_commits_path, remaining_commits.join("\n")) else FileUtils.rm_f(remaining_commits_path) end end
save_state(state)
click to toggle source
# File lib/leg/representations/git.rb, line 275 def save_state(state) @state = state if state.nil? FileUtils.rm_f(state_path) else File.write(state_path, state.to_yaml) end end
state_path()
click to toggle source
# File lib/leg/representations/git.rb, line 262 def state_path File.join(@config.path, ".leg/state.yml") end
step_path()
click to toggle source
# File lib/leg/representations/git.rb, line 245 def step_path File.join(@config.path, "step") end