Main record manipulation class. Handles the loading and saving of records
as both jobs and files.
:files |
[R] |
|
:id |
[RW] |
|
:meta |
[RW] |
|
:seq |
[RW] |
|
:spec |
[RW] |
|
:table |
[RW] |
|
Load a record from its associated job. Use to load existing records rather
than constructing new ones. Raises a RuntimeError if the record does not
exist.
# File P4table.rb, line 427
def P4Record.load( id )
if ( ! P4Record.exists?( id ) )
raise( RuntimeError, "Record #{id.to_s} does not exist", caller )
end
rec = P4Record.new( id )
rec.spec = P4Global.tagged.fetch_job( id.to_s )
if rec.spec.has_key?( "files" )
rec.spec[ "files" ].each do
|file|
name = file.sub( ".*/", "" ).chomp
f = P4RecFile.new( name, id )
f.exists = true
f.depot_path = file.chomp
rec.files[ name ] = f
end
end
rec.exists = true
return rec
end
Load all records matching a query expression. Uses a dynamically built
"p4 jobs -e" expression to identify the matching records and then
loads each record. Returns an array of P4Record
objects.
# File P4table.rb, line 454
def P4Record.query( table, expr )
expr = "job=#{table} & ( " + expr + " )"
P4Global.tagged.run_jobs( "-e", expr ).collect do
|job|
rec = P4Record.new( P4RecId.new_from_job( job[ "job" ] ) )
rec.spec = job
rec.spec[ "files" ].each do
|file|
name = file.sub( ".*/", "" ).chomp
f = P4RecFile.new( name, id )
f.exists = true
f.depot_path = file
rec.files[ name ] = f
end
rec.exists = true
rec
end
end
Create a new record in the given table. Returns the skeletal record
populated with the default values from the jobspec for editing.
# File P4table.rb, line 477
def P4Record.create( table )
id = P4RecId.next( table )
rec = P4Record.new( id )
rec.spec = P4Global.tagged.fetch_job( id.to_s )
return rec
end
Test for record existence
# File P4table.rb, line 487
def P4Record.exists?( id )
jobs = P4Global.tagged.run_jobs( "-e", "job=" + id.to_s )
return jobs.length > 0
end
Constructor: DON'T USE NEW DIRECTLY, CALL create/load.
# File P4table.rb, line 495
def initialize( id )
@id = id
@table = id.table
@seq = id.seq
@spec = nil
@exists = false
@files = Hash.new
@files[ "meta" ] = P4RecFile.new( "meta", @id )
end
Test for record existence
# File P4table.rb, line 512
def exists?
return @exists
end
Explicitly set record existence (or otherwise)
# File P4table.rb, line 519
def exists=( bool )
@exists = bool
end
Get a file handle by name (not the depot path). Returns a P4RecFile object.
# File P4table.rb, line 528
def get_file( name )
return @files[ name ] if @files.has_key?( name )
raise( RuntimeError, "Record contains no file called #{name}", caller )
end
Get the meta file specifically. Just shorthand.
# File P4table.rb, line 536
def metafile
get_file( "meta" )
end
Iterate over the files in the record
# File P4table.rb, line 543
def each_file
@files.each_value { |f| yield( f ) }
end
Add a new file attachment to this record
# File P4table.rb, line 550
def add_file( name )
if ( name == "meta" )
raise( RuntimeError, "The meta file already exists.", caller )
end
nfile = P4RecFile.new( name, @id )
nfile.add
@files[ "name" ] = nfile
end
# File P4table.rb, line 563
def rm_file( file )
if ( file == "meta" )
raise( RuntimeError, "You can't delete the meta file", caller )
end
f = get_file( file )
f.delete
@files.delete( file )
end
Abandon all edits to this record. Use with care: it reverts the files that
are open for add/edit/delete etc. but it doesn't reload the record from the
job - it may be a new record. You should either discard the record or
reload it yourself after calling abandon().
# File P4table.rb, line 580
def abandon
p4 = P4Global.tagged
each_file do
|f|
fs = p4.run_fstat( f.ws_path )
if ( fs && fs[ "action" ] == "add" )
File.unlink( f.ws_path )
end
p4.run_revert( f.depot_path )
end
end
Get the list of files attached to this record in depot syntax
# File P4table.rb, line 595
def file_list
@files.values.collect do
|f|
f.depot_path
end.compact.join( "\n" )
end
Update the record. Updates the job and then archives the job into the meta
file and saves any attached files. Provide the description you'd like to
see attached to the change
# File P4table.rb, line 608
def save( desc )
# First rewrite the files list in case it's been modified
@spec[ "files" ] = file_list
# Next update the job with the values in the spec
P4Global.tagged.save_job( @spec )
# Now update the metafile with the job -o output
if ( exists? )
metafile.edit
else
metafile.add
end
metafile.mkdir
metafile.write( P4Global.plain.fetch_job( @id.to_s ) )
# Now submit
change = P4Global.tagged.fetch_change
change[ "Description" ] = desc
P4Global.tagged.submit_spec( change )
@exists = true
end
Delete a record. Deletes the files and the job.
# File P4table.rb, line 636
def delete( desc )
if ( ! exists? )
raise( RuntimeError, "Can't delete. Record doesn't exist.", caller )
end
@files.values.each { |f| f.delete }
change = P4Global.tagged.fetch_change
change[ "Description" ] = desc
P4Global.tagged.submit_spec( change )
P4Global.tagged.run_job( "-d", @spec[ "job" ] )
@files = Hash.new
@spec[ "files" ] = Array.new
@exists = false
end
Obliterate a record. Does exactly what it says on the tin.
# File P4table.rb, line 655
def obliterate
if ( ! exists? )
raise( RuntimeError, "Can't oblit. Record doesn't exist.", caller )
end
args = @files.values.collect { |f| f.depot_path }
P4Global.tagged.exception_level = 1
P4Global.tagged.run_sync( args.collect { |a| a += "#none" } )
P4Global.tagged.exception_level = 2
P4Global.tagged.run_obliterate( "-y", args )
P4Global.tagged.run_job( "-d", @spec[ "job" ] )
@spec[ "files" ] = Array.new
@files = Hash.new
@exists = false
end
method_missing( meth, *args )
|
Allow direct access to the fields in the jobspec by making them virtual
method names of the form _<field>()
# File P4table.rb, line 675
def method_missing( meth, *args )
meth = meth.to_s
raise if ( meth[0..0] != "_" )
meth = meth[ 1..-1 ]
if ( meth =~ /^(.*)=$/ )
meth = $1
@spec[ meth ] = args.shift
elsif ( args.length == 0 && @spec.has_key?( meth ) )
@spec[ meth ]
else
""
end
end