#!/usr/bin/env ruby
#
# Copyright (c) Perforce Software, Inc., 2014. All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE
# SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#
# Triggers:
# CreateThumbnails change-commit ... "/path/to/file/CreateThumbnails.rb
# %serverport% %change%"
#
# Usage: CreateThumbnails.rb serverport change [-r]
#
#
# Description:
# Goes through the changelist looking for files that can be given a
# thumbnail. Creates the PNG thumbnails using imagemagick, then sends
# the thumbnail to the server as a hex string.
#
# By default this trigger will attempt to make a thumbnail of any file
# that has an extension. For instance, it will try and fail to make a
# thumbnail for .txt and .sh files. If you would like to restrict the
# file types that this trigger will attempt to make thumbnails for, use
# the '-r' option, and add the extension to the 'exts' array. The case of
# the extensions does not matter.
# SET THESE OR TRIGGER WILL NOT WORK
p4bin = '/usr/local/bin/p4'
convertbin = '/usr/local/bin/convert'
user = 'example'
client = 'example-ws'
passwd = 'secret'
# ALL SET
exts = []
exts << 'ppm' << 'bmp' << 'jpg' << 'jpeg' << 'bpm'<< 'gif' << 'pgm' << 'png'
exts << 'xbm' << 'xpm' << 'tga' << 'psd' << 'ai'
describe_regex = /^.+(\/\/[^\/]+[^\.]*?([^\/]+)(\.([^#]+)){1}#[0-9]+).+$/
# With the example string '... //depot/images/flower.png#1 add'
# '//depot/images/flower.png#1' = '\1'
# 'flower' = '\2'
# 'png' = '\4'
lbrFile_regex = /\A.*lbrFile\s+\/\/([^\n]+).*\z/m #'\1' = file
lbrRev_regex = /\A.*lbrRev\s+([^\n]+).*\z/m #'\1' = rev
lbrType_regex = /\A.*lbrType\s+([^\n]+).*\z/m #'\1' = type
require 'zlib'
require 'tempfile'
def bin_to_hex(s)
s.each_byte.map {|b| b.to_s(16).rjust(2, '0')}.join
end
def valid_ext?(extension, exts)
exts.each do |ext|
return true if (0 == extension.casecmp(ext))
end
return false
end
begin
if ARGV.length < 2 || ARGV.length > 3
puts 'Usage: CreateThumbnails.rb serverport change [-r]'
exit 1
end
if ARGV.length == 3
if (ARGV[2] != '-r')
puts 'Usage: CreateThumbnails.rb serverport change [-r]'
exit 1
end
end
serverport = ARGV[0]
change = ARGV[1]
opt3 = ARGV[2]
p4 = "#{p4bin} -p #{serverport} -u #{user} -c #{client} -P #{passwd}"
# Filter changed files and add them to files list
files = []
describe_output = `#{p4} describe -s #{change}`
describe_output.each_line do |line|
if line =~ describe_regex
valid_ext = true
if ('-r' == opt3)
extension = line.gsub(describe_regex, '\4').chomp
valid_ext = valid_ext?(extension, exts)
end
files << line if (valid_ext)
end
end
# Try to make a thumbnail for each file in list
files.each do |file|
begin
depot_file_full = file.gsub(describe_regex, '\1').chomp
file_name = file.gsub(describe_regex, '\2').chomp
fstat_output = `#{p4} fstat -Oc #{depot_file_full}`
lbrFile = fstat_output.gsub(lbrFile_regex, '\1')
lbrRev = fstat_output.gsub(lbrRev_regex, '\1')
lbrType = fstat_output.gsub(lbrType_regex, '\1')
if ('binary' == lbrType || 'ubinary' == lbrType)
lbr_file_full = "#{lbrFile.downcase},d/#{lbrRev}"
# Binary files must be decompressed and contents stored in temp file
if (lbrType == 'binary')
lbr_file_gz = "#{lbr_file_full}.gz"
temp_file = Tempfile.new(file_name)
temp_file.write(Zlib::GzipReader.open(lbr_file_gz) {|gz| gz.read})
lbr_file_full = temp_file.path
end
thumb_name = "#{file_name}_CreateThumbnails_thumb.png"
if system("#{convertbin} #{lbr_file_full} \
-thumbnail 240x240^ #{thumb_name} 2>/dev/null")
thumb_string = File.read(thumb_name)
hex_image = bin_to_hex(thumb_string)
File.open(thumb_name, "w") {|f| f.write(hex_image)}
`cat #{thumb_name} | #{p4} attribute -e -f -n thumb -i \
#{depot_file_full}`
File.delete(thumb_name)
end
temp_file.unlink if (lbrType == 'binary')
end
rescue Zlib::GzipReader::Error
end
end
end
exit 0