lib/gjp/project.rb in gjp-0.11.1 vs lib/gjp/project.rb in gjp-0.11.2

- old
+ new

@@ -3,14 +3,15 @@ require 'find' module Gjp # encapsulates a Gjp project directory class Project - def log - Gjp.logger - end + include Logger + # list of possible statuses + @@statuses = [:gathering, :dry_running] + attr_accessor :full_path def initialize(path) @full_path = Gjp::Project.find_project_dir(File.expand_path(path)) end @@ -35,174 +36,200 @@ end # inits a new project directory structure def self.init(dir) Dir.chdir(dir) do - `git init` - - Dir.mkdir("src") - File.open(File.join("src", "README"), "w") do |file| - file.puts "Sources are to be placed in subdirectories named after Maven names: orgId_artifactId_version" + if Dir.exists?(".git") == false + `git init` end - Dir.mkdir("kit") - File.open(File.join("kit", "README"), "w") do |file| - file.puts "Build tool binaries are to be placed here" - end + copy_from_template "file_lists", "." + copy_from_template "src", "." + copy_from_template "kit", "." + `git add .` `git commit -m "Project initialized"` - `git tag init` + + # automatically begin a gathering phase + Project.new(".").gather end end + # copies a file/dir from the template directory to the destination directory + def self.copy_from_template(template_file, destination_dir) + FileUtils.cp_r(File.join(File.dirname(__FILE__), "..", "template", template_file), destination_dir) + end + # starts a gathering phase, all files added to the project # will be added to packages (including kit) def gather from_directory do - if get_status(:gathering) - return :gathering - elsif get_status(:dry_running) - return :dry_running + status = get_status + if status == :gathering + return false + elsif status == :dry_running + finish end - set_status(:gathering) - commit_all("Gathering started") + set_status :gathering + take_snapshot "Gathering started", :revertable end - :done + true end # starts a dry running phase: files added to the kit will # be added to packages, while sources will be reset at the # end def dry_run from_directory do - if get_status(:gathering) - return :gathering - elsif get_status(:dry_running) - return :dry_running + status = get_status + if status == :dry_running + return false + elsif status == :gathering + finish end - set_status(:dry_running) - commit_all("Dry-run started") + set_status :dry_running + take_snapshot "Dry-run started", :revertable end - :done + true end # ends any phase that was previously started, # generating file lists def finish from_directory do - if get_status(:gathering) - commit_all("Changes during gathering") + status = get_status + if status == :gathering + take_snapshot "Changes during gathering" - update_changed_file_list("kit", "gjp_kit_file_list") - update_changed_src_file_list(:file_list) - commit_all("File list updates") + update_changed_file_list("kit", "kit") + update_changed_src_file_list(:input) + take_snapshot "File list updates" - clear_status(:gathering) - commit_all("Gathering finished") + set_status nil + take_snapshot "Gathering finished", :revertable :gathering - elsif get_status(:dry_running) - commit_all("Changes during dry-run") + elsif status == :dry_running + take_snapshot "Changes during dry-run" - update_changed_file_list("kit", "gjp_kit_file_list") - update_changed_src_file_list(:produced_file_list) - commit_all("File list updates") + update_changed_file_list("kit", "kit") + update_changed_src_file_list(:output) + take_snapshot "File list updates" - revert("src", 2) - commit_all("Sources reverted as before dry-run") + revert("src") + take_snapshot "Sources reverted as before dry-run" - clear_status(:dry_running) - commit_all("Dry run finished") + set_status nil + take_snapshot "Dry run finished", :revertable :dry_running end end end def update_changed_src_file_list(list_name) Dir.foreach("src") do |entry| - if File.directory?(File.join(Dir.getwd, "src", entry)) and entry =~ /([^_\/]+_[^_]+_[^_]+)$/ - update_changed_file_list(File.join("src", entry), "gjp_#{$1}_#{list_name.to_s}") + if File.directory?(File.join(Dir.getwd, "src", entry)) and entry =~ /([^:\/]+:[^:]+:[^:]+)$/ + update_changed_file_list(File.join("src", entry), "#{$1}_#{list_name.to_s}") end end end - def update_changed_file_list(directory, list_file) - existing_files = if File.exists?(list_file) + def update_changed_file_list(directory, file_name) + list_file = File.join("file_lists", file_name) + tracked_files = if File.exists?(list_file) File.readlines(list_file) else [] end - files = ( + new_tracked_files = ( `git diff-tree --no-commit-id --name-only -r HEAD`.split("\n") .select { |file| file.start_with?(directory) } .map { |file|file[directory.length + 1, file.length] } - .concat(existing_files) + .concat(tracked_files) .sort .uniq ) - log.debug("writing file list for #{directory}: #{files.to_s}") + log.debug("writing file list for #{directory}: #{new_tracked_files.to_s}") File.open(list_file, "w+") do |file_list| - files.each do |file| + new_tracked_files.each do |file| file_list.puts file end end end # adds the project's whole contents to git - def commit_all(message) - Find.find(".") do |path| - if path =~ /.gitignore$/ - puts "Deleting #{path} to preserve all files..." - File.delete(path) - end - end - + # if tag is given, commit is tagged + def take_snapshot(message, revertability = :not_revertable) log.debug "committing with message: #{message}" `git rm -r --cached .` `git add .` `git commit -m "#{message}"` + + if revertability == :revertable + latest_count = if latest_snapshot_name =~ /^gjp_revertable_snapshot_([0-9]+)$/ + $1 + else + 0 + end + `git tag gjp_revertable_snapshot_#{$1.to_i + 1}` + end end + # returns the last snapshot git tag name + def latest_snapshot_name + `git describe --abbrev=0 --tags --match=gjp_revertable_snapshot_*`.strip + end + # reverts dir contents as commit_count commits ago - def revert(dir, commit_count) + def revert(dir) `git rm -rf --ignore-unmatch #{dir}` - `git checkout -f HEAD~#{commit_count} -- #{dir}` + `git checkout -f #{latest_snapshot_name} -- #{dir}` `git clean -f -d #{dir}` end - # gets a project status flag - def get_status(status) - file_name = status_file_name(status) - File.exists?(file_name) + # returns a symbol with the current status + # flag + def get_status + from_directory do + @@statuses.each do |status| + if File.exists?(status_file_name(status)) + return status + end + end + end + + nil end - # sets a project status flag + # sets a project status flag. if status = nil, + # clears all status flags def set_status(status) - file_name = status_file_name(status) - if File.exists?(file_name) == false - FileUtils.touch(file_name) - end - end + from_directory do + @@statuses.each do |a_status| + file_name = status_file_name(a_status) + if File.exists?(file_name) + File.delete(file_name) + end - # sets a project status flag - def clear_status(status) - file_name = status_file_name(status) - if File.exists?(file_name) - File.delete(file_name) + if a_status == status + FileUtils.touch(file_name) + end + end end end + # returns a file name that represents a status def status_file_name(status) ".#{status.to_s}" end # runs a block from the project directory