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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3a33dc12a8f5e6304cf6408d9aa711b206173a00
4
- data.tar.gz: e9a9c2af51c18f19a22f8267cdade878f69b40e8
3
+ metadata.gz: 069a887b3fabfbb41e4014f0351e9ad79e699ee9
4
+ data.tar.gz: 6fc582c57a30740878523f1265eade7bd6d24749
5
5
  SHA512:
6
- metadata.gz: 2864edc78108d670eaabd5e4b0e868a46950c3b2cffcb62c9920b0e09ba8c4827036359869b70ddddb4fbf1b2f4e4cc8cc7f4fa4627c6d7026897378488564f4
7
- data.tar.gz: a1dc0543c17c29071686891eec720d25d0987aa4e5a4e9750b698cd57b8c06c474368720b94e30201de7773449a6fb5898bffb5d0b876ebe3ec18a583b88b4cc
6
+ metadata.gz: a055d9ca2f41db3f61c9f8d3969d8b5ef506759671437d157eec182af6eb8ff18ff0567704203b4c4755b2deff87806cc2867ac98e0f161de93c52245f3c24e2
7
+ data.tar.gz: fa442bde271cf8387ac423ae2ba3fc9b8a88d38bd396478998990a8c1c74fb14f37065700acdf0e2276a89562143a25705038a8a85ba95bae5813de9382595da
@@ -2,5 +2,5 @@
2
2
  # format, with a RubyGems-style suffix for 'prereleases'. Please use your branch
3
3
  # as the prerelease label.
4
4
  module P4WebAPI
5
- VERSION = '2014.2.0.pre1'
5
+ VERSION = '2014.2.0.pre2'
6
6
  end
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.pre1
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-25 00:00:00.000000000 Z
11
+ date: 2014-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler