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.join 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(']') header = section.first values = section.last.lstrip.split("\n") section_values = {} values.each do | value | key, value = value.split('=') section_values[key.strip] = value.strip end sections << {header => section_values} end sections end def sections_to_json(config) out = { 'description' => '', 'branches'=> {}} config.each do | section | if section.keys.include? '@repo' out['description'] = section.values.first['description'] else branch = section.values.first['git-branch-name'] # section.values.first.tap {|k| k.delete('git-branch-name')} if section.values.first.include? 'view' view = section.values.first['view'].match(/(?"?.*\/...)\s(?.*)/) section.values.first['depot_path'] = HWSStrings.gf_decode(view['depot_path']) section.values.first['client_path'] = view['client_path'] values = section.values.first.tap {|hs| hs.delete('view')} end out['branches'][branch] = values end end out end def is_header?(value) !value.match(/\[.*\]/).nil? end def get_branch_sections(repo, branches) out = '' branches.each do | branch, values| if values['git-branch-name'].nil? branch_name = branch else branch_name = values['git-branch-name'] values.delete('git-branch-name') end config = <<-EOC.gsub(/^\s*/, '') [#{branch_name}] git-branch-name = #{branch_name} EOC values.each do | key, value | if key == 'depot_path' value = value.gsub(HWSStrings.gf_decode(repo), repo) view = "view = #{value} #{values['client_path']}\n" config << view elsif key != 'client_path' config << "#{key} = #{value}\n" end end out << config out << "\n" end out end def deep_merge(merge_to, merge_from) merged = merge_to.clone merge_from.each do |key, value| # Only override existing key if merged.keys.include?(key) # Deep merge for nested hash if value.is_a?(Hash) && merged[key].is_a?(Hash) merged[key] = deep_merge(merged[key], value) else merged[key] = value end end end merged end def modify_config(old_config, new_config, change_id, p4) old_config = parse_to_hash(old_config) main_section_matches = (new_config.keys - old_config.keys).empty? branches_defined = !new_config['branches'].nil? if branches_defined branch_matches = (new_config['branches'].keys - old_config['branches'].keys).empty? error_and_clean_up(PATCH_PARAMS_DONT_EXIST, change_id, p4) unless main_section_matches && branch_matches config = deep_merge(old_config,new_config) else config = old_config.merge(new_config) end config end end end