Support streams and fix Marshal for 'p4 cstat'
authorPaul Allen <pallen@perforce.com>
Tue, 24 Jun 2014 12:57:30 +0000 (13:57 +0100)
committerPaul Allen <pallen@perforce.com>
Tue, 24 Jun 2014 12:57:30 +0000 (13:57 +0100)
README.markdown
lib/puppet/provider/vcsrepo/p4.rb

index 575950c..d977886 100644 (file)
@@ -346,15 +346,15 @@ defining `p4config`.  If a configuration is defined, then the environment variab
 
 #####To create/update and sync a Perforce workspace
 
-To sync a depot path to head (latest):
+To sync a depot path to head, ensure `latest`:
 
     vcsrepo { "/path/to/repo":
-        ensure   => present,
+        ensure   => latest,
         provider => p4,
         source   => '//depot/branch/...'
     }
 
-For a specific changelist, use `revision`:
+For a specific changelist, ensure `present` and specify a `revision`:
 
     vcsrepo { "/path/to/repo":
         ensure   => present,
index 612cc56..da9c953 100644 (file)
@@ -7,7 +7,7 @@ Puppet::Type.type(:vcsrepo).provide(:p4, :parent => Puppet::Provider::Vcsrepo) d
   
   def create
     # create or update client 
-    create_client(client_name, @resource.value(:path))
+    create_client(client_name)
     
     # if source provided, sync client
     source = @resource.value(:source)
@@ -63,13 +63,19 @@ Puppet::Type.type(:vcsrepo).provide(:p4, :parent => Puppet::Provider::Vcsrepo) d
   def revision
     args = ['cstat']
     args.push(@resource.value(:source))
-    hash = p4(args)
+    hash = p4(args, {:marshal => false})
+    hash = marshal_cstat(hash)
     
-    if hash['status'] == "have"
-      return hash['change'].to_i
-    else
-      return 0
+    revision = 0
+    if hash && hash['code'] != 'error'
+       hash['data'].each do |c|
+         if c['status'] == 'have'
+               change = c['change'].to_i
+               revision = change if change > revision
+         end
+       end
     end
+    return revision
   end
 
   def revision=(desired)
@@ -93,7 +99,7 @@ Puppet::Type.type(:vcsrepo).provide(:p4, :parent => Puppet::Provider::Vcsrepo) d
     Puppet.debug "Syncing: #{source}"
     args = ['sync']
     if revision
-      args.push(source + "@" + revision)
+      args.push(source + "@#{revision}")
     else
       args.push(source)
     end
@@ -127,11 +133,29 @@ Puppet::Type.type(:vcsrepo).provide(:p4, :parent => Puppet::Provider::Vcsrepo) d
   # Params:
   # +client+:: Name of client workspace
   # +path+:: The Root location of the Perforce client workspace
-  def create_client(client, path)
+  def create_client(client)
     Puppet.debug "Creating client: #{client}"
+    
+    # fetch client spec
     hash = parse_client(client)
-    hash['Root'] = path
+    hash['Root'] = @resource.value(:path)
     hash['Description'] = "Generated by Puppet VCSrepo"
+    
+    # check is source is a Stream 
+    source = @resource.value(:source)
+    if source
+      parts = source.split(/\//)
+      if parts && parts.length >= 4
+        source = "//" + parts[2] + "/" + parts[3]
+        streams = p4(['streams', source], {:raise => false})
+        if streams['code'] == "stat"
+          hash['Stream'] = streams['Stream']
+          notice "Streams" + streams['Stream'].inspect
+        end
+      end
+    end
+    
+    # save client spec
     save_client(hash)
   end
 
@@ -212,9 +236,11 @@ Puppet::Type.type(:vcsrepo).provide(:p4, :parent => Puppet::Provider::Vcsrepo) d
       end
       
       # Raise errors, Perforce or Exec
-      if(opts[:raise])
-        p4_err = "P4: " + hash['data'] if(hash['code'] == 'error') 
-        raise Puppet::DevError, "#{p4_err}\n#{e.read}\nExit: #{t.value}" if(t.value != 0)
+      if(opts[:raise] && !e.eof && t.value != 0)
+        raise Puppet::Error, "\nP4: #{e.read}"
+      end
+      if(opts[:raise] && hash['code'] == 'error' && t.value != 0)
+        raise Puppet::Error, "\nP4: #{hash['data']}"
       end
     end
     
@@ -222,4 +248,30 @@ Puppet::Type.type(:vcsrepo).provide(:p4, :parent => Puppet::Provider::Vcsrepo) d
     return hash
   end
   
+  # helper method as cstat does not Marshal
+  def marshal_cstat(hash)
+       data = hash['data']
+       code = 'error'
+       
+       list = Array.new
+       change = Hash.new
+       data.each_line do |l|
+               p = /^\.\.\. (.*) (.*)$/
+               m = p.match(l)
+               if m 
+        change[m[1]] = m[2]
+                 if m[1] == 'status'
+                       code = 'stat'
+                       list.push change
+                       change = Hash.new
+                 end
+               end
+       end
+       
+       hash = Hash.new
+       hash.store 'code', code
+       hash.store 'data', list
+       return hash
+  end
+  
 end