require 'net/http' require 'p4_util' module Cloud class Projects def initialize(env: nil) @env = env @user = env['AUTH_CREDENTIALS'].first @token = env['AUTH_CREDENTIALS'].last end def list(details: false, extension: nil, env: nil) # GET (cloud url)/api/v1/projects uri = URI("#{Settings.cloud_settings[:helix_cloud_url]}/api/v1/projects") # auth.credentials.first == username # auth.credentials.last == session token req = Net::HTTP::Get.new(uri) req['Cookie'] = @token req['Content-Type'] = 'application/json' res = Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(req) } return nil if res.code != '200' list = JSON(res.body) if details return list else return list.map { |n| HWSStrings.component_encode(n['name']) } end end def fetch(id, env: nil) # env.AUTH_CREDENTIALS has our token (in last) # GET (cloud url)/api/v1/project/:id uri = URI("#{Settings.cloud_settings[:helix_cloud_url]}/api/v1/projects/#{id}") # auth.credentials.first == username # auth.credentials.last == session token req = Net::HTTP::Get.new(uri) req['Cookie'] = @token req['Content-Type'] = 'application/json' res = Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(req) } return nil if res.code != '200' project = JSON(res.body) # project[:service] = self return project end # Returns the project's "details" based on the project name. # # No validation is done to ensure this directory actually exists in the # system. def fetch_by_name(name) # TODO : do we need this? raise Exception end # Generate a new client that only contains the project mapping. # # The client name is a combination of user, project, and device. We prefix # it with "_hve" just for clarity. # # We do not host lock the client. # # @param project_id {String} Our encoded project name # @param device {String} A device ID, like a hostname # @param root {String} The `Root` value for the client parameter def create_client(client_name, project_id, root) project = project_from_id(project_id) client_spec = p4.fetch_client(client_name) client_spec._root = root client_spec._host = nil client_spec._options = 'allwrite noclobber nocompress unlocked nomodtime rmdir'; client_spec._stream = project['stream'] results = p4.save_client(client_spec) client_name end # Find the latest submitted change for the project # # Use the 'p4 changes -m 1 -s submitted [depot path]' # # @param project_id [String] The encoded project ID def find_latest_change_for_project(project_id) project = project_from_id(project_id) results = p4.run_changes('-m', '1', '-s', 'submitted', "#{project['stream']}/...") results.first['change'] unless results.empty? end # The HVE project 'changelist' is a pending changelist whose description is # `_hws_[user]_[project_id]` # # We use 'changes -l' to find the change to match potentially long project # names. def find_pending_change_for_project(project_id) results = p4.run_changes('-l', '-u', user, '-s', 'pending') change = results.find { |r| r['desc'].include?(project_id) } change['change'] if change end # If the user doesn't have a current pending change for the project, # create one, and return that. def create_pending_change(project_id) change = find_pending_change_for_project(project_id) return change if change change_spec = p4.fetch_change change_spec._description = "_hws_#{user}_#{project_id}" save_results = p4.save_change(change_spec) change = save_results.first.gsub(/Change (\d+) created./, '\1') # If we don't reset the client of this pending change, we won't be able # to cleanup the temporary client. change_spec = p4.fetch_change(change) change_spec._client = 'INVALID' p4.save_change(change_spec) change end def user @user end protected def p4 @env['p4'] end def project_from_id(project_id) project = fetch(project_id) # TODO: make these better exceptions? # if project.nil? || project['server'] != p4.port # puts "PROJECT '#{project_id}' IS NOT FOUND" if project.nil? # puts "PROJECT '#{project_id}' IS NOT ON CONFIGURED P4PORT!!! #{project['server']} != #{p4.port}" if !project.nil? # puts caller # end raise Exception if project.nil? || project['server'] != p4.port return project end end end