Class: Lich::Util::Update::ScriptSync Private

Inherits:
Object
  • Object
show all
Defined in:
documented/common/update/script_sync.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Bulk SHA-based synchronizer for script repositories.

Downloads scripts and data files from configured SCRIPT_REPOS and custom repos, skipping files where local SHA1 matches the remote SHA1. Supports :all (auto-sync all .lic files except -setup variants) and :explicit (sync only tracked scripts) modes.

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ ScriptSync

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of ScriptSync.

Parameters:



26
27
28
# File 'documented/common/update/script_sync.rb', line 26

def initialize(client)
  @client = client
end

Instance Method Details

#filter_syncable_scripts(tree, config, repo_key = nil) ⇒ Array<Hash>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Filters tree entries to syncable scripts based on tracking mode.

Parameters:

  • tree (Array<Hash>)

    GitHub tree API response

  • config (Hash)

    repository config from SCRIPT_REPOS or custom repo

  • repo_key (String, nil) (defaults to: nil)

    repository key for tracked script lookup

Returns:

  • (Array<Hash>)

    filtered tree entries



155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'documented/common/update/script_sync.rb', line 155

def filter_syncable_scripts(tree, config, repo_key = nil)
  candidates = tree.select { |e| e['path'] =~ config[:script_pattern] && e['type'] == 'blob' }

  case config[:tracking_mode]
  when :all
    candidates.reject { |e| File.basename(e['path']).include?('-setup') }
  when :explicit
    tracked = TrackedScripts.new.tracked_scripts(config, repo_key: repo_key)
    candidates.select { |e| tracked.include?(File.basename(e['path'])) }
  else
    candidates
  end
end

#sync_all_reposvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Syncs all registered repositories (built-in + custom) for current game.



33
34
35
36
# File 'documented/common/update/script_sync.rb', line 33

def sync_all_repos
  SCRIPT_REPOS.each_key { |repo_key| sync_repo(repo_key) }
  CustomRepos.all.each_key { |repo_key| sync_repo(repo_key) }
end

#sync_repo(repo_key, force: false) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Syncs a single repository by key (built-in or custom).

Parameters:

  • repo_key (String)

    repository key from SCRIPT_REPOS or custom repo

  • force (Boolean) (defaults to: false)

    skip SHA check and download all (default: false)



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'documented/common/update/script_sync.rb', line 43

def sync_repo(repo_key, force: false)
  config = SCRIPT_REPOS[repo_key]
  unless config
    # Check custom repos
    reg = CustomRepos.all[repo_key]
    if reg
      config = CustomRepos.build_config(repo_key, reg)
    else
      known = (SCRIPT_REPOS.keys + CustomRepos.all.keys).join(', ')
      respond "[lich5-update: Unknown repository '#{repo_key}'. Known: #{known}]"
      return
    end
  end

  if config[:game_filter] && XMLData.game !~ config[:game_filter]
    return
  end

  tree_data = @client.fetch_github_json(config[:api_url])
  unless tree_data && tree_data['tree']
    respond "[lich5-update: Failed to fetch tree for #{repo_key}.]"
    return
  end
  tree = tree_data['tree']

  name = config[:display_name] || repo_key
  syncable = filter_syncable_scripts(tree, config, repo_key)
  StatusReporter.respond_mono("[lich5-update: Syncing #{name} (#{syncable.length} scripts)...]")

  # Custom repos write to their per-repo subdir; built-in repos to SCRIPT_DIR
  dest = config[:dest_dir] || SCRIPT_DIR
  FileUtils.mkdir_p(dest) if config[:custom]

  local_shas = FileWriter.build_local_sha_map(dest)
  downloaded_scripts = []
  failed_scripts = []
  syncable.each do |entry|
    filename = File.basename(entry['path'])
    next if !force && local_shas[filename] == entry['sha']

    content = @client.http_get("#{config[:raw_base_url]}/#{entry['path']}", auth: false)
    unless content
      failed_scripts << filename
      next
    end

    begin
      FileWriter.safe_write(File.join(dest, filename), content)
      downloaded_scripts << filename
    rescue StandardError => e
      respond "[lich5-update: write failed for #{filename}: #{e.message}]"
      failed_scripts << filename
    end
  end

  downloaded_other = {}
  failed_other = {}
  (config[:subdirs] || {}).each do |subdir_name, subconfig|
    files, failures = sync_subdir(tree, config, subdir_name, subconfig)
    downloaded_other[subdir_name] = files unless files.empty?
    failed_other[subdir_name] = failures unless failures.empty?
  end

  StatusReporter.render_sync_summary(name, syncable.length, downloaded_scripts, downloaded_other, config[:subdirs]&.keys || [], failed_scripts, failed_other)
end

#sync_subdir(tree, config, _subdir_name, subconfig) ⇒ Array<Array<String>>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Syncs a subdirectory (profiles, data) from repository.

Parameters:

  • tree (Array<Hash>)

    GitHub tree API response

  • config (Hash)

    repository config from SCRIPT_REPOS

  • _subdir_name (String)

    subdirectory name (unused)

  • subconfig (Hash)

    subdirectory config (pattern, dest, glob)

Returns:

  • (Array<Array<String>>)

    [downloaded_files, failed_files]



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'documented/common/update/script_sync.rb', line 116

def sync_subdir(tree, config, _subdir_name, subconfig)
  pattern = subconfig[:pattern]
  dest = subconfig[:dest]
  return [[], []] unless pattern && dest

  FileUtils.mkdir_p(dest)
  entries = tree.select { |e| e['path'] =~ pattern && e['type'] == 'blob' }
  return [[], []] if entries.empty?

  local_shas = FileWriter.build_local_sha_map(dest, subconfig[:glob] || '*.yaml')
  downloaded = []
  failed = []
  entries.each do |entry|
    filename = File.basename(entry['path'])
    next if local_shas[filename] == entry['sha']

    content = @client.http_get("#{config[:raw_base_url]}/#{entry['path']}", auth: false)
    unless content
      failed << filename
      next
    end

    begin
      FileWriter.safe_write(File.join(dest, filename), content)
      downloaded << filename
    rescue StandardError => e
      respond "[lich5-update: write failed for #{filename}: #{e.message}]"
      failed << filename
    end
  end
  [downloaded, failed]
end