Class: Nsync::Producer

Inherits:
Consumer show all
Defined in:
lib/nsync/producer.rb,
lib/nsync/producer/methods.rb

Overview

The Nsync::Producer is used to tend to the repo and allow files to be written out and changesets to be commited. It is a subclass of the Nsync::Consumer, which allows a Producer to consume itself. This gives it the ability to perform rollbacks and undo misstakes in that way

Basic Usage:

Nsync::Config.run do |c|
  # The producer uses a standard repository
  # This will automatically be created if it does not exist
  c.repo_path = "/local/path/to/hold/data"
  # The remote repository url will get data pushed to it
  c.repo_push_url = "git@examplegithost:username/data.git"

  # This must be Nsync::GitVersionManager if you want things like
  # rollback to work.
  c.version_manager = Nsync::GitVersionManager.new

  # A lock file path to use for this app
  c.lock_file = "/tmp/app_name_nsync.lock"
end

# make some changes that get written out to the repo

@producer = Nsync::Producer.new

@producer.commit("Some nice changes for you")

Defined Under Namespace

Modules: InstanceMethods Classes: Change

Instance Attribute Summary

Attributes inherited from Consumer

#repo

Instance Method Summary collapse

Methods inherited from Consumer

#after_class_finished, #after_current_class_finished, #after_finished, #changes, #config, #first_commit, #initialize, #remotes, #reprocess_class!

Constructor Details

This class inherits a constructor from Nsync::Consumer

Instance Method Details

#commit(message = "Friendly data update", which_changes = :all) ⇒ Object

Commits and pushes the current changeset

By default all changes in working dir are committed.

Alternatively, specific changes can be specified in the which_changes parameter. The format for this is => [id,…]



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/nsync/producer.rb', line 109

def commit(message="Friendly data update", which_changes=:all)
  config.lock do
    config.cd do
      
      files_to_commit = []
      latest_changes.each do |klass, changes|
        which_of_class = which_changes[klass.to_s] if which_changes.is_a?(Hash)
        changes.each do |change|
          if which_changes == :all || 
            (which_of_class && which_of_class.include?(change.id))

            files_to_commit << 
              File.join(config.repo_path, diff_path(change.diff))
          end
        end
      end
      repo.git.update_index({:add => true, :remove => true}, '--', *files_to_commit)

      repo.commit_index(message)
      config.log.info("[NSYNC] Committed '#{message}' to repo")
    end
  end
  push
end

#diff_untracked_filesObject

gets untracked files into the diff output hack from stackoverflow.com/questions/855767/can-i-use-git-diff-on-untracked-files



91
92
93
94
95
96
97
98
99
100
# File 'lib/nsync/producer.rb', line 91

def diff_untracked_files
  # TODO: change to using --work-tree in git
  config.cd do
    response, err = repo.git.sh(<<-CMD)
      git --git-dir='#{repo.git.git_dir}' ls-files -d --others --exclude-standard  |
        while read -r i; do git --git-dir='#{repo.git.git_dir}' diff --full-index -- /dev/null "$i"; done
    CMD
    response
  end
end

#file_exists?(filename) ⇒ Boolean

Determines whether a file at ‘filename’ exists in the working tree

Returns:

  • (Boolean)


30
31
32
# File 'lib/nsync/producer.rb', line 30

def file_exists?(filename)
  File.exists?(File.join(config.repo_path, filename))
end

#latest_changesObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/nsync/producer.rb', line 74

def latest_changes
  # TODO: change to using --work-tree in git
  diff = config.cd { repo.git.native('diff', {:full_index => true}) }
  diff += diff_untracked_files

  if diff =~ /diff --git a/
    diff = diff.sub(/.*?(diff --git a)/m, '\1')
  else
    diff = ''
  end

  diffs = Grit::Diff.list_from_string(repo, diff)
  changeset_from_diffs(diffs, Change)
end

#pushObject

Pushes all changes to the repo_push_url



135
136
137
138
139
140
141
142
143
# File 'lib/nsync/producer.rb', line 135

def push
  if config.remote_push?
    config.cd do
      repo.git.push({}, config.repo_push_url, "+master")
      config.log.info("[NSYNC] Pushed changes")
    end
  end
  true
end

#remove_file(filename) ⇒ Object

Removes a file from the repo at ‘filename’



58
59
60
61
# File 'lib/nsync/producer.rb', line 58

def remove_file(filename)
  FileUtils.rm File.join(config.repo_path, filename)
  config.log.info("[NSYNC] Removed file '#{filename}'")
end

#rollbackObject

Returns data to its state at HEAD~1 and sets HEAD to that This new HEAD state is pushed to the repo_push_url. Hooray git.



147
148
149
150
151
152
153
154
155
# File 'lib/nsync/producer.rb', line 147

def rollback
  commit_to_rollback = config.version_manager.version
  commit_to_rollback_to = config.version_manager.previous_version
  config.cd do
    repo.git.reset({:hard => true}, commit_to_rollback_to)
    apply_changes(commit_to_rollback, commit_to_rollback_to)
  end
  push
end

#write_file(filename, hash, add = false) ⇒ Object

Writes a file to the repo at ‘filename’ with content in json from the hash

Parameters:

  • filename (String)

    path in the working tree to write to

  • hash (Hash)

    a hash that can be converted to json to be written

  • add (Boolean) (defaults to: false)

    tells whether to git add the file.

    This is for internal bookkeeping files only



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/nsync/producer.rb', line 41

def write_file(filename, hash, add=false)
  config.cd do
    dir = File.dirname(filename)
    unless [".", "/"].include?(dir) || File.directory?(dir)
      FileUtils.mkdir_p(File.join(config.repo_path, dir))
    end

    File.open(File.join(config.repo_path, filename), "w") do |f|
      f.write( (hash.is_a?(Hash))? hash.to_json : hash )
    end
    repo.add(File.join(config.repo_path, filename)) if add
    config.log.info("[NSYNC] Updated file '#{filename}'")
  end
  true
end