Skip to content

CODE_WIKI English version

bcggxx edited this page Jul 27, 2026 · 1 revision

fast-clone Code Wiki

Mirror-accelerated git clone tool that automatically resets remote to the official address after cloning. Core value: Download from mirror sites (fast), subsequent pull/push go through the official repo (secure). Zero external dependencies: Uses only the Python standard library.


Table of Contents


1. Project Overview

fast-clone is a command-line tool written in Python that accelerates cloning GitHub / GitLab repositories under restricted network conditions. It downloads repository content through mirror sites (prefix proxy, domain replacement, etc.) and automatically resets the origin remote to the official address after cloning, balancing "fast downloads" with "safe subsequent pull/push".

Feature Description
Safe and worry-free Automatically resets remote to official address after cloning
Auditable code Pure-text Python source, no binaries, no obfuscation
Zero dependencies Uses only the Python standard library, no pip install needed
Smart protection Speed monitoring + auto-retry + direct-connect fallback
Multi-mirror support 11 built-in mirrors, 4 transformation strategies
Network adaptive Auto-detects local IPv4/IPv6 support, skips unavailable mirrors
Speed-test cache Speed-test results reused within 7 days, avoiding repeated tests
Daily status report GitHub Actions runs daily tests and publishes reports as Releases
Bilingual support Auto-detects and switches between Chinese and English
Highly customizable Edit mirror.json to add/remove mirrors, effective on next run

License: MIT License, Copyright (c) 2026 bcggxx.


2. Project Architecture

fast-clone adopts a minimal architecture of single-file core + separated config/i18n, divided into three layers:

┌─────────────────────────────────────────────────────────────┐
│                  User CLI / CI                               │
│   fast-clone <url> [--fastest] [--mirror xxx] [-n] ...       │
└───────────────┬─────────────────────────────────────────────┘
                │
                ▼
┌─────────────────────────────────────────────────────────────┐
│  Core Layer  fastclone.py  (single file, zero ext deps)      │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐  │
│  │ Config   │ │ URL      │ │ Mirror   │ │  IPv4/IPv6     │  │
│  │ Loading  │ │ Parsing  │ │ Transform│ │  Detection     │  │
│  └──────────┘ └──────────┘ └──────────┘ └────────────────┘  │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐  │
│  │ Speed    │ │ Speed    │ │ Clone    │ │  Terminal      │  │
│  │ Test+Cache│ │ Monitor │ │ Flow     │ │  Color Output  │  │
│  └──────────┘ └──────────┘ └──────────┘ └────────────────┘  │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Setup Mode (Windows PATH injection) / main() entry  │   │
│  └──────────────────────────────────────────────────────┘   │
└──────┬──────────────────┬───────────────────┬───────────────┘
       │ reads            │ reads/writes       │ imports
       ▼                  ▼                   ▼
┌─────────────┐    ┌─────────────┐     ┌─────────────┐
│ mirror.json │    │ speedcache/ │     │  i18n.py    │
│ mirror cfg  │    │ speed cache │     │ biling text │
└─────────────┘    └─────────────┘     └─────────────┘

┌─────────────────────────────────────────────────────────────┐
│  CI Layer  .github/workflows/mirror-test.yml                 │
│  Daily UTC 08:00 → scripts/test_mirrors.py → gen report      │
│  → overwrite mirror-status Release                           │
└─────────────────────────────────────────────────────────────┘

Architecture characteristics:

  • Single-file core: fastclone.py contains all business logic (~1200 lines), no third-party dependencies.
  • Config/code separation: Mirror list in mirror.json, text in i18n.py, modifications don't touch core code.
  • Runtime data isolation: Speed-test cache writes to speedcache/ (gitignored), doesn't pollute the repo.
  • Platform wrappers: windows/fast-clone.cmd and the wrapper created by linux/setup.sh both point to the in-place fastclone.py, config paths remain unchanged.

3. Directory Structure

fast-clone/                     ← keep this directory fixed after install
├── fastclone.py                ← core script (main logic, ~1200 lines)
├── i18n.py                     ← bilingual text and language detection
├── mirror.json                 ← mirror config (11 mirrors + default params)
├── scripts/
│   └── test_mirrors.py         ← GitHub Actions connectivity test script
├── .github/workflows/
│   └── mirror-test.yml         ← daily mirror status Release workflow
├── windows/
│   ├── setup.bat               ← Windows install entry (calls --setup)
│   └── fast-clone.cmd          ← Windows command wrapper
├── linux/
│   └── setup.sh                ← Linux install script (creates wrapper)
├── README.md                   ← Chinese usage docs
├── README.en.md                ← English usage docs
├── LICENSE                     ← MIT license
├── .gitignore                  ← ignores speedcache/, mirror-test-report.md, etc.
├── speedcache/                 ← (runtime-generated) speed-test cache dir
└── mirror-test-report.md       ← (CI-generated) test report, gitignored

4. Core Module Responsibilities

Module Responsibility Independently editable
fastclone.py Core business logic: arg parsing, URL transformation, IP detection, speed test, clone monitoring, auto-retry, remote reset, Setup mode Yes (core code)
i18n.py System language detection (Windows LCID / Unix env vars) + bilingual text table _T + L()/Lh() translation functions Yes (text isolated)
mirror.json Mirror config: default mirror, speed threshold, timeout, retry count, mirror dict (each mirror has name/platforms/transform/test_host/ip, etc.) Yes (edit takes effect immediately)
scripts/test_mirrors.py CI-only: reads mirror.json, concurrent TCP 443 speed test, generates bilingual Markdown report, read-only, never modifies mirror.json Yes
.github/workflows/mirror-test.yml Daily scheduled task: runs speed-test script → overwrites mirror-status Release Yes
windows/setup.bat Windows install entry, checks Python then calls fastclone.py --setup Yes
windows/fast-clone.cmd Windows command wrapper: detects Python and forwards args to fastclone.py Yes
linux/setup.sh Linux install script: checks Python/Git, creates wrapper script pointing to in-place fastclone.py Yes

5. Key Classes and Functions

5.1 Config Loading (fastclone.py)

Config is loaded from mirror.json in the same directory as fastclone.py, read once at startup and cached as module-level variable _CONFIG.

Function Location Description
_load_mirror_config() fastclone.py#L49 Loads config from mirror.json; falls back to empty-mirror config if file missing/corrupt, ensuring the tool can still direct-clone
load_config() fastclone.py#L81 Returns the cached _CONFIG dict
get_mirrors(config) fastclone.py#L85 Gets the mirrors sub-dict
get_default_mirror(config) fastclone.py#L89 Gets default mirror key, defaults to 'gh-proxy-org'
get_speed_threshold(config) fastclone.py#L93 Gets speed threshold (KiB/s), defaults to 1024 (1 MB/s)
get_speed_timeout(config) fastclone.py#L97 Gets speed timeout seconds, defaults to 180
get_connect_retries(config) fastclone.py#L101 Gets connection retry count, defaults to 3

mirror.json top-level fields:

{
  "default": "gh-proxy-org",
  "speed_threshold_kib": 1024,
  "speed_timeout_seconds": 180,
  "connect_retries": 3,
  "mirrors": { ... }
}

5.2 URL Parsing and Platform Detection

Parses user-input repository URLs (HTTPS or SSH) into structured info for subsequent mirror transformation.

Function Location Description
parse_git_url(url) fastclone.py#L127 Parses git URL, supports both git@host:path (SSH) and https://host/path formats; returns dict with original/official/domain/owner/repo/platform/is_ssh/is_wiki/https_url
_split_path(path) fastclone.py#L109 Splits path into (owner, repo, is_wiki); recognizes .wiki / .wiki.git suffix for Wiki repos, Wiki clone URLs don't get .git appended
_make_info(...) fastclone.py#L142 Assembles parsed result dict, generates normalized https_url and display official address
_detect_platform(domain) fastclone.py#L159 Identifies platform from domain: github / gitlab (incl. jihulab) / gitee / unknown

Returned info dict structure:

{
    'original':  'git@github.com:user/repo.git',   # original input
    'official':  'git@github.com:user/repo',        # display addr without .git
    'domain':    'github.com',
    'owner':     'user',
    'repo':      'repo',
    'platform':  'github',
    'is_ssh':    True,
    'is_wiki':   False,
    'https_url': 'https://github.com/user/repo.git' # base URL for mirror transform
}

5.3 Mirror URL Transformation (4 Strategies)

apply_mirror(info, mirror) (fastclone.py#L174) selects a strategy based on mirror['transform'] field, converting the official HTTPS URL to a mirror URL:

Strategy Required fields Transformation example
prefix prefix https://mirror.com/ + https://github.com/user/repo.git
domain_replace old, new github.comkkgithub.com (replaces first match only)
path_prefix prefix https://gitclone.com/github.com/ + user/repo (strips protocol and domain)
domain_suffix old, suffix github.comgithub.com.mirror.org

Unknown strategy raises ValueError.

5.4 IPv4/IPv6 Network Protocol Detection

Detects local network protocol support at startup, used to filter unreachable mirrors (e.g., skip IPv6-only mirrors in environments without IPv6).

Function / Variable Location Description
_IP_SUPPORT fastclone.py#L199 Module-level cache: (has_ipv4, has_ipv6) or None (not detected)
_IPV4_PROBES / _IPV6_PROBES fastclone.py#L204 Probe endpoints: Cloudflare first, falls back to Tencent DNSPod (avoids false-negative when Cloudflare is blocked)
_probe_ip(family, addr, timeout) fastclone.py#L208 TCP 443 connection probe to specified address, returns bool
_probe_ip_any(family, addrs, timeout) fastclone.py#L220 Tries address list sequentially, returns True on first success
detect_ip_support(timeout) fastclone.py#L228 Parallel IPv4/IPv6 detection, result cached to _IP_SUPPORT; does not filter when both stacks fail (lets real clone decide); returns (has_v4, has_v6)
filter_mirrors_by_ip(mirrors, has_v4, has_v6) fastclone.py#L257 Filters mirrors by mirror['ip'] field (dual/v4/v6); not applied when --mirror is explicit

5.5 Speed Test and Cache

In --fastest mode, concurrent TCP speed tests pick the fastest mirror; results cached to speedcache/ directory, valid for 7 days.

Function Location Description
_CACHE_DIR fastclone.py#L283 Cache directory: speedcache/ next to script
_CACHE_EXPIRE_DAYS fastclone.py#L284 Cache validity: 7 days
_cache_dir() fastclone.py#L287 Ensures cache dir exists and returns it
_cache_filename(dt) fastclone.py#L293 Cache filename = test time (YYYY-MM-DD_HHMMSS.json, Windows-safe no colons)
_find_valid_cache(platform) fastclone.py#L298 Finds the most recent valid (non-expired) cache entry for platform, None if not found
_save_cache(platform, results) fastclone.py#L325 Persists speed-test results, filename is test timestamp
_find_expired_caches() fastclone.py#L339 Lists expired (>7 days) or corrupt cache files
prompt_delete_expired_caches() fastclone.py#L362 Asks at startup whether to delete expired caches (default Y delete)
_tcp_latency(host, port, timeout) fastclone.py#L386 Single mirror TCP 443 latency test, returns float('inf') on failure
_get_speed_results(platform, candidates, timeout) fastclone.py#L396 Speed-test main logic: check cache first → if miss, concurrent live test → write cache; returns {mirror_key: latency_seconds}
find_fastest_mirror(info, mirrors, config, timeout) fastclone.py#L445 Selects fastest mirror: filter by platform → IP filter → speed test → pick lowest latency; falls back to default mirror if all unreachable

Cache file format:

{
  "test_time": "2026-07-06T05:54:54",
  "platform": "github",
  "results": {
    "gh-proxy-org": {"latency_ms": 188.0, "reachable": true},
    "kkgithub": {"latency_ms": null, "reachable": false}
  }
}

5.6 Clone Speed Monitoring

During cloning, parses git clone --progress stderr output in real-time, monitors download speed, aborts and switches mirror if low speed persists beyond timeout.

Function / Class Location Description
_SPEED_RE fastclone.py#L478 Speed regex: matches 123.45 MiB/s or 678 KiB/s
_LOCAL_PHASES fastclone.py#L479 Local phase keywords (bilingual): updating files / 更新文件 etc., these phases don't participate in speed judgment
_CONN_ERRS fastclone.py#L486 Connection error keyword list (could not resolve host / connection timed out, etc.)
_PROGRESS_SIZE_RE fastclone.py#L495 Progress regex: matches 12.3 MiB | 1.5 MiB/s (cumulative size + current speed)
_render_progress(line) fastclone.py#L508 Renders git stderr lines into human-readable real-time progress (received object size + speed), TTY-only display
_parse_speed(line) fastclone.py#L552 Parses speed line, returns (speed_kib, is_local_phase)
_is_connection_error(text) fastclone.py#L564 Determines if it's a connection-class error (used to distinguish retry vs switch)
SpeedMonitor fastclone.py#L569 Speed monitoring class: thread-safe tracking of last speed-OK time; feed(line) feeds log lines, should_abort() decides whether to abort, stalled property returns stalled seconds
_stderr_reader(proc, monitor, collected, abort) fastclone.py#L596 Background thread: reads git stderr, feeds monitor, renders progress, triggers abort
_safe_kill(proc) fastclone.py#L616 Cross-platform safe process kill: Windows uses taskkill /T, Linux uses process group SIGTERMSIGKILL
clone_with_monitor(mirror_url, target_dir, clone_args, min_kib, timeout_sec) fastclone.py#L635 Single clone execution: starts git clone --progress, monitors speed, returns status dict (ok/speed_timeout/connection_error/other_error)

SpeedMonitor class:

class SpeedMonitor:
    def __init__(self, min_kib, timeout_sec): ...
    def feed(self, line): ...        # feed log line, refresh _ok time if meets threshold
    def should_abort(self) -> bool:  # True if stalled beyond timeout
    @property
    def stalled(self) -> float:      # current stalled seconds

5.7 Main Clone Flow (Auto-Retry + Mirror Switching)

Function Location Description
clone_with_fallback(info, url, args, config, mirror_keys) fastclone.py#L694 Core clone flow: iterates mirror list, each mirror retries per connect_retries; on success resets remote and returns; speed timeout switches to next; connection errors retry; all failures fall back to direct official clone
_set_remote(tp, url) fastclone.py#L794 Resets origin remote to official address after successful clone (SSH addresses also set back to original SSH)
_resolve_mirror_list(args, info, config) fastclone.py#L805 Resolves mirror candidate list: filter by platform → IP filter (when not --mirror) → --fastest speed-test sort / --mirror specified first / default mirror first; --dry-run skips speed test and cache writes
_build_clone_args(args, url) fastclone.py#L1181 Builds git clone args (--progress + branch/depth/single-branch + url + target + extra)

clone_with_fallback state machine:

res['status'] Meaning Handling
ok Clone succeeded Reset remote, return 0
speed_timeout Speed persistently below threshold Switch to next mirror (no retry)
connection_error Connection-class error Retry (up to connect_retries times), switch when exhausted
other_error Other errors (incl. git not installed) Switch to next mirror

Safety protections: refuses to clone into current working directory; refuses to delete current working directory (prevents accidental user data loss).

5.8 Terminal Output and Color Support

Function / Class Location Description
Color fastclone.py#L842 Color output class: defines ANSI color codes; enable() enables VT mode on Windows (SetConsoleMode), Unix checks isatty(); c(text, code) wraps color
Color._enabled fastclone.py#L870 One-time determination at module load whether to enable colors
print_separator() fastclone.py#L873 Prints cyan separator line
print_header(title) fastclone.py#L877 Prints separator block with title
print_step(msg) fastclone.py#L883 Cyan -> step hint
print_ok(msg) fastclone.py#L887 Green OK success hint
print_warn(msg) fastclone.py#L891 Yellow ! warning
print_err(msg) fastclone.py#L895 Red X error
die(msg, code) fastclone.py#L899 Prints error then sys.exit(code)
run_git(args, **kw) fastclone.py#L904 Wraps subprocess.run(['git'] + args)

5.9 Setup Mode

On Windows, setup.batfastclone.py --setup triggers interactive installation.

Function Location Description
_ps_quote(s) fastclone.py#L912 PowerShell safe single-quote escaping
_add_to_path(target, machine) fastclone.py#L917 Uses PowerShell [Environment]::SetEnvironmentVariable to add directory to user/system PATH (avoids setx 1024-char truncation), deduplicates, returns 'ok'/'already'/'fail'
_cmd_setup() fastclone.py#L959 Interactive install flow: check Git → choose PATH install method (user/system/manual) → add PATH → verify (list mirrors) → done

5.10 Entry Point main()

main() (fastclone.py#L1040) is the program entry, flow:

  1. Load config, build argparse parser (with full args and bilingual help)
  2. --setup → go to install flow
  3. --list-mirrors → list all mirrors
  4. No url → print help
  5. parse_git_url() parses URL
  6. Unknown platform → warn and direct-clone
  7. _resolve_mirror_list() resolves mirror candidates
  8. Print repository info (platform/repo name/official URL/preferred mirror/fallback mirrors, etc.)
  9. --dry-run → preview URL transformation, no clone
  10. prompt_delete_expired_caches() asks to clean expired caches
  11. clone_with_fallback() executes clone

Complete CLI arguments:

Argument Short Description
url Official repository URL
--mirror -m Specify mirror key
--fastest -f Auto speed-test, pick fastest
--timeout -t Speed-test timeout seconds (default 3)
--list-mirrors -l List all mirrors
--branch -b Specify branch
--depth -d Shallow clone depth
--single-branch Single branch only
--target Target directory name
--min-speed Minimum speed MB/s
--speed-timeout Speed timeout seconds
--no-set-url Do not reset remote (debug)
--dry-run -n Preview without cloning
--setup (hidden) Setup mode
--help -h Help

5.11 Internationalization (i18n.py)

Function / Variable Location Description
detect_language() i18n.py#L19 System language detection: ① env var FASTCLONE_LANG takes priority; ② Windows uses GetUserDefaultUILanguage/GetSystemDefaultUILanguage/GetUserDefaultLCID (only recognizes zh-CN 0x0804, excludes zh-TW/HK); ③ Unix checks LC_ALL/LC_MESSAGES/LANG/LANGUAGE; ④ locale.getlocale(); ⑤ defaults to zh (tool ships CN mirrors, primarily targets CN users)
LANG i18n.py#L94 Module-level constant, detected once at startup
_T i18n.py#L101 Bilingual text dict: {key: {'zh': ..., 'en': ...}}, contains all user-visible text for mirror/repo/clone/speed-test/cache/IP/dry-run/error/setup
L(key, *args) i18n.py#L213 Looks up text by key and formats with args; falls back to English then to key itself when missing
Lh(zh, en) i18n.py#L219 One-off bilingual helper for ad-hoc strings like argparse help

Language override: FASTCLONE_LANG accepts zh/cn/chinese/zh-cn/zh_cn/zh-hans and en/english.

5.12 Daily Mirror Test Script (scripts/test_mirrors.py)

CI-only script, read-only on mirror.json, never modifies it.

Function / Variable Location Description
MIRROR_JSON / REPORT_FILE test_mirrors.py#L29 Config and report paths (project root)
_detect_runner_ipv6() test_mirrors.py#L32 Probes whether CI runner supports IPv6 (Cloudflare anycast :443)
RUNNER_HAS_IPV6 test_mirrors.py#L45 Module-level constant, runner IPv6 capability
load_mirrors() test_mirrors.py#L48 Loads mirror.json
tcp_latency(host, port, timeout) test_mirrors.py#L53 Single mirror TCP 443 latency test, returns (latency_ms, error)
test_mirror(key, mirror, timeout) test_mirrors.py#L64 Tests single mirror: IPv6 mirrors skipped on runners without IPv6
main() test_mirrors.py#L75 Concurrent speed test → generates bilingual Markdown table report → writes file + prints + appends GITHUB_STEP_SUMMARY; returns non-zero when more than half unreachable (for CI alerting)

6. Dependencies

6.1 External Dependencies

Zero external Python package dependencies, uses only the Python standard library:

Standard library module Purpose
argparse Command-line argument parsing
datetime Speed-test cache time judgment
json Read/write mirror.json and cache files
os / shutil File/directory operations, cross-platform checks
re Parse git progress output, URL parsing
signal Process group signals (Linux process kill)
socket TCP speed test, IPv4/IPv6 detection
subprocess Call git, PowerShell (Windows PATH)
sys Standard stream reconfiguration (Windows UTF-8), exit
threading Speed monitor thread, thread lock
time Speed-test timing, retry delay
concurrent.futures Concurrent speed test (ThreadPoolExecutor)
pathlib Path handling
urllib.parse URL parsing
ctypes (Windows) Call kernel32 for language, enable VT mode
locale Unix language detection fallback

System dependencies:

Dependency Version Description
Python 3.7+ Uses from __future__ import annotations and type annotation syntax
Git any Must be in PATH, calls git clone --progress

6.2 Internal Module Dependencies

fastclone.py
  ├── depends on → i18n.py  (L, Lh, LANG)
  ├── reads → mirror.json  (loads _CONFIG at startup)
  └── reads/writes → speedcache/*.json  (speed-test cache)

scripts/test_mirrors.py
  └── reads → mirror.json  (read-only, never modifies)

windows/fast-clone.cmd ──calls──> fastclone.py
windows/setup.bat      ──calls──> fastclone.py --setup
linux/setup.sh         ──creates wrapper──> fastclone.py

.github/workflows/mirror-test.yml ──calls──> scripts/test_mirrors.py

6.3 Key Call Chain

main()
 ├─ load_config() / get_mirrors() / get_default_mirror() ...
 ├─ parse_git_url() → _split_path() / _make_info() / _detect_platform()
 ├─ _resolve_mirror_list()
 │   ├─ detect_ip_support() → _probe_ip_any() → _probe_ip()
 │   ├─ filter_mirrors_by_ip()
 │   └─ find_fastest_mirror() → _get_speed_results()
 │       ├─ _find_valid_cache()  (check cache)
 │       └─ _tcp_latency() × N  (concurrent live test) → _save_cache()
 ├─ prompt_delete_expired_caches() → _find_expired_caches()
 └─ clone_with_fallback()
     ├─ apply_mirror()  (4 strategies)
     ├─ clone_with_monitor()
     │   ├─ SpeedMonitor.feed() / should_abort()
     │   ├─ _stderr_reader() → _render_progress() / _parse_speed()
     │   └─ _safe_kill()  (abort)
     ├─ _set_remote()  (reset after success)
     └─ run_git()  (fallback direct clone)

7. How to Run

7.1 Get the Tool

git clone https://github.com/bcggxx/fast-clone.git

Keep the repo in a fixed local location; do not move the directory after installation.

7.2 Installation

Windows

cd fast-clone\windows
setup.bat

The install script checks Python/Git (PATH only) and adds fast-clone\windows\ to PATH. After that, fast-clone is available in any terminal.

Linux

cd fast-clone/linux
bash setup.sh

The install script creates a wrapper pointing to the in-place fastclone.py (~/.local/bin user-level or /usr/local/bin system-level); mirror.json path stays the same.

Prerequisites

Dependency Install
Python 3.7+ python.org or package manager
Git git-scm.com or package manager

7.3 Direct Run (Without Install)

# Linux/macOS
python3 fastclone.py [args] [repo-url]

# Windows
python fastclone.py [args] [repo-url]

7.4 Usage Examples

# Default gh-proxy.org mirror
fast-clone https://github.com/user/repo

# Auto speed-test, pick fastest mirror
fast-clone --fastest https://github.com/user/repo

# Specify mirror
fast-clone --mirror github-akams https://github.com/user/repo

# Preview transformation, no clone
fast-clone -n https://github.com/user/repo

# List all mirrors
fast-clone -l

# Specify branch + shallow clone
fast-clone -b main --depth 1 https://github.com/user/repo

# Custom speed threshold
fast-clone --min-speed 2 --speed-timeout 120 https://github.com/user/repo

7.5 Language Switching

# Force English
export FASTCLONE_LANG=en

# Force Chinese
export FASTCLONE_LANG=zh

7.6 Updates

cd /path/to/fast-clone
git pull
  • Wrapper points to in-place fastclone.py, takes effect without reinstall
  • Mirror list auto-syncs with git pull
  • speedcache/ is gitignored, unaffected

8. Configuration Reference (mirror.json)

8.1 Top-Level Fields

Field Type Default Description
default string "gh-proxy-org" Default mirror key
speed_threshold_kib int 1024 Speed threshold (KiB/s), i.e., 1 MB/s
speed_timeout_seconds int 180 Timeout seconds for speed persistently below threshold
connect_retries int 3 Connection failure retry count per mirror
mirrors object Mirror dict, key is mirror identifier

8.2 Mirror Fields

Field Required Description
name yes Mirror display name
platforms yes Supported platforms list, e.g., ["github"], ["gitlab"]
transform yes Transform strategy: prefix / domain_replace / path_prefix / domain_suffix
test_host yes Hostname for speed test (TCP 443 connectivity test)
ip no Protocol filter: dual (default) / v4 / v6
description yes Description text
prefix required for prefix/path_prefix Prefix URL
old / new required for domain_replace Source/target for domain replacement
old / suffix required for domain_suffix Source/suffix for domain suffix append

8.3 Built-in Mirror List (11)

key Mirror site Platform Strategy IP
gh-proxy-org * gh-proxy.org github prefix dual
gh-proxy-v4 v4.gh-proxy.org github prefix v4
gh-proxy-v6 v6.gh-proxy.org github prefix dual
gh-proxy-cdn cdn.gh-proxy.org github prefix v4
gh-proxy-com gh-proxy.com github prefix dual
ghproxy-net ghproxy.net github prefix dual
kkgithub kkgithub.com github domain_replace dual
github-akams github.akams.cn github prefix dual
gitclone gitclone.com github path_prefix v4
github-ur1 github.ur1.fun github domain_replace dual
jihulab jihulab.com gitlab domain_replace dual

* is the default mirror.

8.4 Adding a Custom Mirror

Edit mirror.json, add an entry under mirrors:

"my-mirror": {
    "name": "my-mirror.example.com",
    "platforms": ["github"],
    "transform": "domain_replace",
    "old": "github.com",
    "new": "my-mirror.example.com",
    "test_host": "my-mirror.example.com",
    "ip": "dual",
    "description": "My self-hosted mirror"
}

Delete an entry to disable it. Modify top-level "default" to switch the default mirror. Takes effect on next run.


9. GitHub Actions Automation

9.1 Workflow File

.github/workflows/mirror-test.yml

  • Triggers: daily UTC 08:00 (Beijing 16:00) schedule + workflow_dispatch manual
  • Permissions: contents: write (create/delete Release and tag)
  • Concurrency: group: mirror-status, cancel-in-progress: false

9.2 Execution Flow

  1. Checkout code
  2. Set up Python 3.13
  3. Run python scripts/test_mirrors.py --timeout 5 (continue-on-error: true, publishes report even when more than half unreachable)
  4. Delete old mirror-status Release + tag (--cleanup-tag)
  5. Create new mirror-status Release, body is full report, attachment is mirror-test-report.md

9.3 Report Characteristics

  • Fixed tag mirror-status: overwritten daily, no history accumulation
  • Release body is full report: click to see each mirror's latency and reachability table
  • Bilingual table: key | mirror | ip | latency | status
  • Read-only: does not modify mirror.json, mirror changes only by manual edit

10. Key Flow Diagrams

10.1 Main Clone Flow

User runs fast-clone <url>
        │
        ▼
   main() parses args
        │
        ▼
  parse_git_url() parses URL
        │
        ▼
  Platform known? ──no──→ warn + direct clone
        │yes
        ▼
  _resolve_mirror_list() resolves mirror candidates
   ├─ detect_ip_support() IP detection
   ├─ filter_mirrors_by_ip() IP filter
   └─ --fastest? ──yes──→ find_fastest_mirror() speed-test sort
        │
        ▼
  Print repo info
        │
        ▼
  --dry-run? ──yes──→ preview URL transform, exit
        │no
        ▼
  prompt_delete_expired_caches() ask to clean cache
        │
        ▼
  clone_with_fallback()  ◄────────────────┐
        │                                  │
        ▼                                  │
  Iterate mirror list (for mk in mirror_keys) │
        │                                  │
        ▼                                  │
  apply_mirror() generate mirror URL       │
        │                                  │
        ▼                                  │
  clone_with_monitor() single clone        │
   ├─ start git clone --progress           │
   ├─ SpeedMonitor monitors speed          │
   └─ _stderr_reader renders progress      │
        │                                  │
        ▼                                  │
   ┌────┴────┐                             │
   │ status? │                             │
   └────┬────┘                             │
   ┌────┼────┬────────┐                    │
   ▼    ▼    ▼        ▼                    │
  ok  speed  conn   other                  │
   │   _timeout error  _error              │
   │   │     │       │                     │
   │   │     │       └──→ switch next ─────┤
   │   │     │                             │
   │   │     ▼                             │
   │   │  retry-- >0? ─yes──→ retry ───────┤
   │   │     │no                           │
   │   │     └──→ switch next ─────────────┤
   │   │                                   │
   │   └──→ switch next ───────────────────┤
   │                                       │
   ▼                                       │
  _set_remote() reset origin to official  │
   │                                       │
   ▼                                       │
  return 0 (success)                      │
                                           │
  Mirror list exhausted ──→ fallback direct clone ──┘

10.2 Speed Test and Cache Flow

--fastest triggers find_fastest_mirror()
        │
        ▼
  Filter candidates by platform
        │
        ▼
  detect_ip_support() + filter_mirrors_by_ip()
        │
        ▼
  _get_speed_results()
        │
        ▼
  Check _find_valid_cache(platform)? ──hit──→ reuse cached results
        │miss
        ▼
  Concurrent _tcp_latency() × N (ThreadPoolExecutor, max 10)
        │
        ▼
  _save_cache() write speedcache/YYYY-MM-DD_HHMMSS.json
        │
        ▼
  Pick lowest-latency mirror, fall back to default if all unreachable

11. Design Highlights and Safety Mechanisms

11.1 Safety Mechanisms

Mechanism Implementation Location
Auto remote reset After successful clone, uses git remote set-url origin <official> to swap mirror address back to official, so subsequent pull/push go through official repo _set_remote()
SSH address handling SSH addresses clone via mirror as HTTPS, remote set back to original SSH after completion parse_git_url() + _set_remote()
Refuse clone to current dir After resolving target dir, checks if equals Path.cwd(), die() if so clone_with_fallback()
Refuse to delete current dir When cleaning leftovers, checks tp.resolve() != Path.cwd().resolve() clone_with_fallback()
Low-speed protection Speed persistently < threshold beyond timeout → abort, clean leftovers, switch mirror SpeedMonitor + clone_with_monitor()
Connection retry Each mirror retries N times on connection failure, switches when exhausted clone_with_fallback()
Direct-connect fallback After all mirrors fail, finally attempts official repo directly end of clone_with_fallback()

11.2 Robustness Design

Design Description
Config missing fallback When mirror.json missing/corrupt, falls back to empty-mirror config, tool still direct-clones
IP detection dual endpoints Cloudflare first, falls back to Tencent DNSPod, avoids false-negative when Cloudflare blocked
IP detection all-fail no filter When both stacks fail, no IP-version filtering, lets real clone decide
Cache corruption tolerance Cache file JSON parse failure treated as expired, doesn't affect operation
Cross-platform process management Windows uses taskkill /T, Linux uses process group SIGTERMSIGKILL
Windows UTF-8 forced sys.stdout.reconfigure(encoding='utf-8') at startup solves Chinese garbling
Windows VT mode Color.enable() calls SetConsoleMode to enable ANSI colors
PATH injection dedup _add_to_path() compares by trailing-slash-stripped lowercase, avoids duplicate accumulation on reinstall
PATH injection avoids truncation Uses PowerShell SetEnvironmentVariable instead of setx (avoids 1024-char truncation)
Speed-test cache isolation speedcache/ is gitignored, git pull doesn't touch local cache
CI read-only test_mirrors.py never modifies mirror.json, mirror changes only manual

11.3 Performance Design

Design Description
Concurrent speed test ThreadPoolExecutor concurrent TCP speed test, up to 10 parallel
Speed-test cache Same-platform speed-test results reused within 7 days, avoids repeated tests
In-process IP cache detect_ip_support() result cached to _IP_SUPPORT, detected only once per run
Module-level config cache _CONFIG loaded once at startup, avoids repeated file reads
Daemon thread stderr reader thread is daemon, auto-ends when main process exits

This Code Wiki is generated based on the fast-clone repository source code, covering project architecture, module responsibilities, key classes and functions, dependencies, how to run, configuration reference, CI automation, and design highlights. For the latest implementation, please read the source files directly.

Clone this wiki locally