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(/(?<depot_path>"?.*\/...)\s(?<client_path>.*)/)
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