p4_web_api 2014.2.0.pre1 → 2014.2.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/p4_web_api/version.rb +1 -1
- data/lib/p4_web_api.rb +154 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 069a887b3fabfbb41e4014f0351e9ad79e699ee9
|
4
|
+
data.tar.gz: 6fc582c57a30740878523f1265eade7bd6d24749
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a055d9ca2f41db3f61c9f8d3969d8b5ef506759671437d157eec182af6eb8ff18ff0567704203b4c4755b2deff87806cc2867ac98e0f161de93c52245f3c24e2
|
7
|
+
data.tar.gz: fa442bde271cf8387ac423ae2ba3fc9b8a88d38bd396478998990a8c1c74fb14f37065700acdf0e2276a89562143a25705038a8a85ba95bae5813de9382595da
|
data/lib/p4_web_api/version.rb
CHANGED
data/lib/p4_web_api.rb
CHANGED
@@ -54,6 +54,7 @@ module P4WebAPI
|
|
54
54
|
configure do
|
55
55
|
set(:p4, 'host' => 'localhost', 'port' => '1666')
|
56
56
|
set(:token_path, '/tmp/p4_web_api/tokens')
|
57
|
+
set(:workspace_folder, '/tmp/p4_web_api/workspaces')
|
57
58
|
|
58
59
|
set(:run_get_blacklist, %w(add change changelist clean copy cstat
|
59
60
|
delete diff edit flush have integ integrate
|
@@ -111,6 +112,65 @@ module P4WebAPI
|
|
111
112
|
P4Util.open(options, &block)
|
112
113
|
end
|
113
114
|
|
115
|
+
# Block helper to open a p4 handle with a temporary client workspace.
|
116
|
+
# The client workspace will map the series of depot path expressions
|
117
|
+
# directly into the client workspace.
|
118
|
+
#
|
119
|
+
# The depot_paths are generally expected to be complete file path
|
120
|
+
# expressions, e.g., '//depot/dir1/dir2/file'. They'll be mapped directly
|
121
|
+
# to the temporary working area: '//client/depot/dir/1/dir2/file'
|
122
|
+
#
|
123
|
+
# The block handler here will be called with the arguments (p4, root),
|
124
|
+
# where root is the temporary client's root directory.
|
125
|
+
def open_p4_temp_client(depot_paths, &block)
|
126
|
+
open_p4 do |p4|
|
127
|
+
name = (0...8).map { (65 + rand(26)).chr }.join
|
128
|
+
dir = init_temp_workspace_dir(name)
|
129
|
+
init_temp_client(p4, name, dir, depot_paths)
|
130
|
+
|
131
|
+
ex = nil
|
132
|
+
begin
|
133
|
+
block.call(p4, dir)
|
134
|
+
rescue StandardError => e
|
135
|
+
ex = e
|
136
|
+
end
|
137
|
+
|
138
|
+
delete_temp_client(p4, name, dir)
|
139
|
+
|
140
|
+
fail ex unless ex.nil?
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def init_temp_workspace_dir(name)
|
146
|
+
dir = File.join(settings.workspace_folder, name)
|
147
|
+
unless Dir.exist?(dir)
|
148
|
+
FileUtils.mkpath(dir)
|
149
|
+
FileUtils.chmod(0700, dir)
|
150
|
+
end
|
151
|
+
dir
|
152
|
+
end
|
153
|
+
|
154
|
+
def init_temp_client(p4, name, dir, depot_paths)
|
155
|
+
spec = p4.fetch_client
|
156
|
+
spec._root = dir
|
157
|
+
spec._client = name
|
158
|
+
spec._description = 'p4_web_api temp client'
|
159
|
+
|
160
|
+
spec._view = depot_paths.map do |path|
|
161
|
+
stripped = path.gsub(/^[\/]*/, '')
|
162
|
+
"\"//#{stripped}\" \"//#{name}/#{stripped}\""
|
163
|
+
end
|
164
|
+
|
165
|
+
p4.save_client(spec)
|
166
|
+
p4.client = name
|
167
|
+
|
168
|
+
p4.run_sync('//...')
|
169
|
+
end
|
170
|
+
|
171
|
+
def delete_temp_client(p4, name, dir)
|
172
|
+
p4.run_client('-d', '-f', name)
|
173
|
+
FileUtils.rmtree(dir)
|
114
174
|
end
|
115
175
|
|
116
176
|
error do
|
@@ -686,6 +746,100 @@ module P4WebAPI
|
|
686
746
|
''
|
687
747
|
end
|
688
748
|
|
749
|
+
# The print method uses the print command underneath to output file content.
|
750
|
+
#
|
751
|
+
# Unlike most of the other methods, this does not output application/json.
|
752
|
+
# If the type contains 'text' we set the Content-Type to 'text/plain',
|
753
|
+
# otherwise it's 'application/octet-stream'.
|
754
|
+
get '/v1/print/*' do
|
755
|
+
path = params[:splat].join('')
|
756
|
+
path = "//#{path}"
|
757
|
+
|
758
|
+
results = nil
|
759
|
+
open_p4 do |p4|
|
760
|
+
results = p4.run_print(path)
|
761
|
+
end
|
762
|
+
|
763
|
+
file_type = results[0]
|
764
|
+
content = results[1]
|
765
|
+
|
766
|
+
if file_type['type'] =~ /text/
|
767
|
+
content_type 'text/plain'
|
768
|
+
else
|
769
|
+
content_type 'application/octet-stream'
|
770
|
+
end
|
771
|
+
|
772
|
+
content
|
773
|
+
end
|
774
|
+
|
775
|
+
# The upload method adds new file revisions.
|
776
|
+
#
|
777
|
+
# This is a multipart method that accepts and array of files, plus,
|
778
|
+
# a 'mappings' array to indicate the target depot path for each file.
|
779
|
+
# This should be a JSON encoded array of strings.
|
780
|
+
#
|
781
|
+
# An optional 'description' attribute can describe the changes to be made.
|
782
|
+
post '/v1/upload' do
|
783
|
+
# if mappings[] and files[] do not have equivalent lengths, the error
|
784
|
+
# might be kind of lame.
|
785
|
+
mappings = params[:mappings]
|
786
|
+
files = []
|
787
|
+
mappings.each_index { |idx| files << params["file_#{idx}".to_sym] }
|
788
|
+
|
789
|
+
open_p4_temp_client(mappings) do |p4, root|
|
790
|
+
message = params[:description] || 'Uploaded files'
|
791
|
+
change_id = init_changelist(p4, message)
|
792
|
+
|
793
|
+
# Information used to determine if the new rev should be an add or edit
|
794
|
+
files_results = p4.run_files(mappings)
|
795
|
+
|
796
|
+
(0...mappings.length).each do |idx|
|
797
|
+
type = existing_path?(files_results, mappings[idx]) ? 'edit' : 'add'
|
798
|
+
|
799
|
+
if type == 'edit'
|
800
|
+
mark_change('edit', p4, change_id, root, mappings[idx])
|
801
|
+
save_content(root, mappings[idx], files[idx])
|
802
|
+
else
|
803
|
+
save_content(root, mappings[idx], files[idx])
|
804
|
+
mark_change('add', p4, change_id, root, mappings[idx])
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
808
|
+
p4.run_submit('-c', change_id)
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
def init_changelist(p4, description)
|
813
|
+
change_spec = p4.fetch_change
|
814
|
+
change_spec._description = description
|
815
|
+
results = p4.save_change(change_spec)
|
816
|
+
results[0].gsub(/^Change (\d+) created./, '\1')
|
817
|
+
end
|
818
|
+
|
819
|
+
def save_content(root, depot_path, file)
|
820
|
+
local_file = local_path(depot_path, root)
|
821
|
+
dir = File.dirname(local_file)
|
822
|
+
FileUtils.mkpath(dir) unless Dir.exist?(dir)
|
823
|
+
|
824
|
+
IO.write(local_file, file[:tempfile].read)
|
825
|
+
end
|
826
|
+
|
827
|
+
def existing_path?(existing_results, depot_path)
|
828
|
+
existing_results.any? do |result|
|
829
|
+
result['depotFile'] == depot_path
|
830
|
+
end
|
831
|
+
end
|
832
|
+
|
833
|
+
def mark_change(type, p4, change_id, root, depot_path)
|
834
|
+
local_file = local_path(depot_path, root)
|
835
|
+
p4.run(type, '-c', change_id, local_file)
|
836
|
+
end
|
837
|
+
|
838
|
+
def local_path(depot_path, root)
|
839
|
+
stripped = depot_path.gsub(/^\/+/, '')
|
840
|
+
File.join(root, stripped)
|
841
|
+
end
|
842
|
+
|
689
843
|
# Basically a "blacklist" of things we know the frameworks going to add to
|
690
844
|
# the params array we don't want to pass on to the p4 command sets for spec
|
691
845
|
# input
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: p4_web_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2014.2.0.
|
4
|
+
version: 2014.2.0.pre2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Perforce Software, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|