Module: Hoe::Perforce

Defined in:
lib/hoe/perforce.rb

Overview

seattle.rb perforce projects are structured as:

project_name/

dev/
  History.txt
  Manifest.txt
  README.txt
  Rakefile
  bin/
  lib/
  test/
  ...
1.0.0/...
1.0.1/...
...

Each release is a branch from project_name/dev to project_name/version. In perforce, branches can be explicit (created via a branch spec) or implicit (created by command-line). This structure can accommodate either but the code below is implicit.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#perforce_ignoreObject

Files fore perforce to ignore. Probably not needed now that they support a dot-ignore file. I have yet to use that so… yeah.



34
35
36
# File 'lib/hoe/perforce.rb', line 34

def perforce_ignore
  @perforce_ignore
end

Instance Method Details

#define_perforce_tasksObject

Defines tasks for the perforce plugin.



46
47
48
49
50
51
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
77
78
79
80
81
82
# File 'lib/hoe/perforce.rb', line 46

def define_perforce_tasks
  warn :define_perforce_tasks if $DEBUG

  desc "branch the project from dev to version dir"
  task :branch do
    original_dir = File.basename(Dir.pwd)

    Dir.chdir ".."

    target_dir = File.directory?(version) ? version : original_dir
    branching  = target_dir == original_dir && target_dir != version
    pkg = File.basename(Dir.pwd)

    begin
      p4_integrate original_dir, version if branching
      validate_manifest_file version
      p4_submit "Branching #{pkg} to version #{version}" if branching
    rescue => e
      warn e
      p4_revert version
      raise e
    end

    Dir.chdir version
  end

  task :prerelease => :branch

  task :postrelease => :announce do
    system 'rake clean'
  end

  desc "Generate historical flog/flay data for all releases"
  task :history do
    p4_history
  end
end

#initialize_perforceObject

Initializes the perforce plugin.



39
40
41
# File 'lib/hoe/perforce.rb', line 39

def initialize_perforce
  self.perforce_ignore = []
end

#p4_historyObject

Return the flog & flay history of all releases.



174
175
176
177
178
179
180
# File 'lib/hoe/perforce.rb', line 174

def p4_history
  history p4_versions do |version|
    Dir.chdir "../#{version}" do
      flog_flay
    end
  end
end

#p4_integrate(from, to) ⇒ Object

Branch a release from from to to.



149
150
151
152
153
# File 'lib/hoe/perforce.rb', line 149

def p4_integrate from, to
  opened = `p4 opened #{from}/... #{to}/... 2>&1`
  raise "You have files open" if opened =~ /\/\/[^#]+#\d+/
  p4sh "p4 integrate #{from}/... #{to}/..."
end

#p4_revert(dir) ⇒ Object

Revert the pending (release) directory.



141
142
143
144
# File 'lib/hoe/perforce.rb', line 141

def p4_revert dir
  puts "reverting #{dir}"
  p4sh "p4 revert #{dir}/..."
end

#p4_submit(description) ⇒ Object

Submit the current directory with a description message.



158
159
160
# File 'lib/hoe/perforce.rb', line 158

def p4_submit description
  p4sh "p4 submit -d #{description.inspect} ..."
end

#p4_versionsObject

Return all version directories (and dev).



165
166
167
168
169
# File 'lib/hoe/perforce.rb', line 165

def p4_versions
  dirs = Dir["../[0-9]*"].sort_by { |s| Gem::Version.new(File.basename(s)) }
  dirs << "../dev"
  dirs.map { |d| File.basename d }
end

#p4sh(cmd) ⇒ Object

perforce has an annoying “feature” that reads PWD and chdir’s to it. Without either mucking in ENV or forcing a different kind of system call, it’ll be in the original rake directory. I don’t want that for these recipes, so we tack on “;” in order to force the right type of exec.



91
92
93
# File 'lib/hoe/perforce.rb', line 91

def p4sh cmd
  sh "#{cmd};"
end

#validate_manifest_file(manifest_dir) ⇒ Object

Audit the manifest file against files on the file system.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/hoe/perforce.rb', line 98

def validate_manifest_file manifest_dir
  manifest_file = "#{manifest_dir}/Manifest.txt"
  raise "#{manifest_file} does not exist" unless test ?f, manifest_file
  manifest = File.new(manifest_file).readlines.map { |x| x.strip }
  manifest -= perforce_ignore

  exclusions = with_config do |config, _|
    config["exclude"]
  end

  local_manifest = []

  Dir.chdir manifest_dir do
    system 'rake clean'
    Find.find '.' do |f|
      next if f =~ exclusions
      local_manifest << f.sub(/^\.\//, '') if File.file? f
    end
  end

  local_manifest -= perforce_ignore

  extra_files   = local_manifest - manifest
  missing_files = manifest - local_manifest

  msg = []

  unless extra_files.empty? then
    msg << "You have files that are not in your manifest"
    msg << "  #{extra_files.inspect}"
  end

  unless missing_files.empty? then
    msg << "You have files that are missing from your manifest"
    msg << "  #{missing_files.inspect}"
  end

  raise msg.join("\n") unless msg.empty?
end