require 'p4_error' require 'json' require 'git_fusion/util' module GitFusion module ConfigParser include Util REPO_MAPPING_NOT_MATCHING = 'Submitted repository configuration does not point to the chosen repository' REPO_CONFIG_JSON_NOT_VALID = 'Submitted repository JSON configuration is not valid' def validate_json_config(config, repo) # must have description # must have branches # depot_path must include chosen endpoint # must have a stream or depot_path and client_path # all keys must be from a known list error_and_clean_up(REPO_CONFIG_JSON_NOT_VALID) unless !config['branches'].nil? or !config['description'].nil? points_to_repo = false config['branches'].values.each do |branch| points_to_repo = true if branch['depot_path'].include? repo end error_and_clean_up(REPO_MAPPING_NOT_MATCHING) unless points_to_repo view_or_stream = false config['branches'].each do |_branch, values| view_or_stream = true if (values.keys.include? 'depot_path' and values.keys.include? 'client_path') or values.keys.include? 'stream' end error_and_clean_up(REPO_CONFIG_JSON_NOT_VALID) unless view_or_stream end def parse_to_hash(config) config = config sections = get_config_sections(config) sections_to_json(sections) end def parse_from_json(repo, config) main_section_keys = config.keys.select { |k| k != 'branches' } main_section = '' main_section_keys.each do |key| main_section << "#{key} = #{config[key]}\n" end branches = config['branches'] branch_sections = get_branch_sections(repo, branches) config = <<-EOC.gsub(/^\s*/, '') [@repo] #{main_section} #{branch_sections} EOC config end def get_config_sections(config) config = config.split('[') config.shift sections = [] config.each do |section| section = section.split(']') values = section.last.lstrip.split("\n") section_values = {} values.each do |value| key, value = value.split('=') section_values[key.strip] = value.strip end sections << { section.first => section_values } end sections end def sections_to_json(config) out = { 'description' => '', 'branches' => {} } config.each do |section| value = section.values.first if section.keys.include? '@repo' out['description'] = value['description'] else branch = value['git-branch-name'] if value.include? 'view' view_mapping = %r{(?"?.*\/...)\s(?.*)} view = value['view'].match(view_mapping) value['depot_path'] = GitFusionStrings.decode(view['depot_path']) value['client_path'] = view['client_path'] values = value.tap { |hs| hs.delete('view') } end out['branches'][branch] = values end end out end def branch_config_section(branch_name) config = <<-EOC.gsub(/^\s*/, '') [#{branch_name}] git-branch-name = #{branch_name} EOC config end def config_line(repo, all_values, key, value) line = '' if key == 'depot_path' value = value.gsub(GitFusionStrings.decode(repo), repo) line = "view = #{value} #{all_values['client_path']}\n" elsif key != 'client_path' line = "#{key} = #{value}\n" end line end def get_branch_sections(repo, branches) config = '' branches.each do |branch, all_values| branch_name = all_values['git-branch-name'] || branch all_values.delete('git-branch-name') branch_config = branch_config_section(branch_name) all_values.each do |key, value| branch_config << config_line(repo, all_values, key, value) end config << "#{branch_config}\n" end config end def deep_merge(merge_to, merge_from) merged = merge_to.clone merge_from.each do |key, value| next unless merged.keys.include?(key) if value.is_a?(Hash) && merged[key].is_a?(Hash) merged[key] = deep_merge(merged[key], value) else merged[key] = value end end merged end def matching_branches?(ms_match, new_branches, old_branches) matches = ms_match && (new_branches.keys - old_branches.keys).empty? fail P4Error.default_error(PATCH_PARAMS_DONT_EXIST) unless matches end def modify_config(oldconf, newconf) oldconf = parse_to_hash(oldconf) ms_matches = (newconf.keys - oldconf.keys).empty? if !newconf['branches'].nil? matching_branches?(ms_matches, newconf['branches'], oldconf['branches']) config = deep_merge(oldconf, newconf) else config = oldconf.merge(newconf) end config end end end