44require "uri"
55require "fileutils"
66require "zip"
7- require_relative "version"
87
98module CF
109 module MCP
1110 class Downloader
1211 CUTE_FRAMEWORK_ZIP_URL = "https://github.com/RandyGaul/cute_framework/archive/refs/heads/master.zip"
12+ GITHUB_ARCHIVE_URL_TEMPLATE = "https://github.com/RandyGaul/cute_framework/archive/%{ref}.zip"
13+ SHA_METADATA_FILE = ".cf-mcp-sha"
1314 DEFAULT_DOWNLOAD_DIR = File . join ( Dir . tmpdir , "cf-mcp-#{ VERSION } " )
1415
1516 class DownloadError < StandardError ; end
@@ -24,23 +25,41 @@ def download_and_extract
2425 zip_path = File . join ( @download_dir , "cute_framework.zip" )
2526 base_path = File . join ( @download_dir , "cute_framework" )
2627 include_path = File . join ( base_path , "include" )
27- File . join ( base_path , "docs" , "topics" )
28+ sha_file = File . join ( @download_dir , SHA_METADATA_FILE )
2829
29- # Return existing path if already downloaded
30- if File . directory? ( include_path ) && !Dir . empty? ( include_path )
31- return include_path
30+ # Check if cache is valid
31+ stored_sha = read_sha_metadata ( sha_file )
32+ latest_sha = fetch_latest_sha
33+
34+ if stored_sha && latest_sha && stored_sha == latest_sha
35+ if File . directory? ( include_path ) && !Dir . empty? ( include_path )
36+ warn "Using cached Cute Framework headers (SHA: #{ stored_sha } )"
37+ return include_path
38+ end
39+ end
40+
41+ # Determine download URL
42+ if latest_sha
43+ download_url = format ( GITHUB_ARCHIVE_URL_TEMPLATE , ref : latest_sha )
44+ warn "Downloading Cute Framework at SHA #{ latest_sha } ..."
45+ else
46+ download_url = CUTE_FRAMEWORK_ZIP_URL
47+ warn "Downloading Cute Framework from master branch..."
3248 end
3349
34- download_zip ( zip_path )
50+ download_zip ( zip_path , download_url )
3551 extract_directories ( zip_path , base_path )
3652
53+ # Store metadata for future cache checks
54+ write_sha_metadata ( sha_file , latest_sha ) if latest_sha
55+
3756 include_path
3857 end
3958
4059 private
4160
42- def download_zip ( destination )
43- uri = URI . parse ( CUTE_FRAMEWORK_ZIP_URL )
61+ def download_zip ( destination , url = CUTE_FRAMEWORK_ZIP_URL )
62+ uri = URI . parse ( url )
4463
4564 Net ::HTTP . start ( uri . host , uri . port , use_ssl : true ) do |http |
4665 request = Net ::HTTP ::Get . new ( uri )
@@ -73,9 +92,9 @@ def extract_directories(zip_path, base_path)
7392 top_level_prefix = nil
7493
7594 zip_file . each do |entry |
76- # Find the top-level directory prefix (e.g., "cute_framework-master/")
77- if top_level_prefix . nil? && entry . name . match? ( %r{^[^/]+/include/} )
78- top_level_prefix = entry . name . match ( %r{^([^/]+/)} ) [ 1 ]
95+ # Find the top-level directory prefix (e.g., "cute_framework-master/" or "cute_framework-abc1234/" )
96+ if top_level_prefix . nil? && entry . name . match? ( %r{^cute_framework- [^/]+/include/} )
97+ top_level_prefix = entry . name . match ( %r{^(cute_framework- [^/]+/)} ) [ 1 ]
7998 break
8099 end
81100 end
@@ -107,6 +126,29 @@ def extract_directories(zip_path, base_path)
107126 end
108127 end
109128 end
129+
130+ def fetch_latest_sha
131+ client = GitHubClient . new
132+ client . latest_commit_sha
133+ rescue => e
134+ warn "GitHub API error: #{ e . message } "
135+ nil
136+ end
137+
138+ def read_sha_metadata ( file )
139+ return nil unless File . exist? ( file )
140+ File . read ( file ) . strip
141+ rescue => e
142+ warn "Error reading SHA metadata: #{ e . message } "
143+ nil
144+ end
145+
146+ def write_sha_metadata ( file , sha )
147+ return unless sha
148+ File . write ( file , sha )
149+ rescue => e
150+ warn "Error writing SHA metadata: #{ e . message } "
151+ end
110152 end
111153 end
112154end
0 commit comments