tui-piechart 0.3.3

A customizable pie chart widget for Ratatui TUI applications
Documentation
#!/usr/bin/env nu
# Migrate a project to dual GitHub + Gitea hosting.
# Adds a Gitea remote, optionally pushes all history, and sets up .gitea/workflows.
#
# Usage: nu scripts/migrate_to_gitea.nu [--project-dir <dir>] [--gitea-url <url>]
# Examples:
#   nu scripts/migrate_to_gitea.nu
#   nu scripts/migrate_to_gitea.nu --gitea-url git@gitea.example.com:user/tui-piechart.git
#   nu scripts/migrate_to_gitea.nu --project-dir /path/to/project --gitea-url <url>

def main [
    --project-dir: string = "",  # Path to the project root (default: current directory)
    --gitea-url: string   = "",  # Full Gitea remote URL (prompted if not supplied)
] {
    let green  = (ansi green)
    let red    = (ansi red)
    let yellow = (ansi yellow)
    let blue   = (ansi blue)
    let cyan   = (ansi cyan)
    let bold   = (ansi --escape {attr: b})
    let reset  = (ansi reset)

    def success [msg: string] { print $"($green)✅ ($msg)($reset)" }
    def info    [msg: string] { print $"($blue)ℹ️  ($msg)($reset)" }
    def warning [msg: string] { print $"($yellow)⚠️  ($msg)($reset)" }
    def heading [msg: string] {
        print $"($cyan)($bold)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━($reset)"
        print $"($cyan)($bold)  ($msg)($reset)"
        print $"($cyan)($bold)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━($reset)"
    }
    def fail [msg: string] {
        print $"($red)❌ Error: ($msg)($reset)"
        exit 1
    }

    # ── Resolve project directory ─────────────────────────────────────────────
    let proj_dir = if ($project_dir | is-empty) {
        $env.PWD
    } else {
        $project_dir | path expand
    }

    if not ($proj_dir | path exists) {
        fail $"Project directory does not exist: ($proj_dir)"
    }

    cd $proj_dir

    # ── Preflight checks ──────────────────────────────────────────────────────
    if (which git | length) == 0 {
        fail "git is not installed. Please install git first."
    }

    let git_check = (do { run-external "git" "rev-parse" "--git-dir" } | complete)
    if $git_check.exit_code != 0 {
        fail $"Not a git repository: ($proj_dir)"
    }

    let project_name = ($proj_dir | path basename)

    print ""
    heading $"Gitea Migration — ($project_name)"
    print ""
    info $"Project directory: ($proj_dir)"
    print ""

    # ── Resolve Gitea URL ─────────────────────────────────────────────────────
    let resolved_url = if ($gitea_url | is-empty) {
        print "Enter your Gitea remote URL."
        print "  SSH  example: git@gitea.example.com:user/tui-piechart.git"
        print "  HTTPS example: https://gitea.example.com/user/tui-piechart.git"
        print ""
        let url = (input "Gitea URL: " | str trim)
        if ($url | is-empty) {
            fail "No Gitea URL provided. Aborting."
        }
        $url
    } else {
        $gitea_url
    }

    # ── Add or update the gitea remote ───────────────────────────────────────
    heading "Configuring Gitea Remote"
    print ""

    let existing_remotes = (do { run-external "git" "remote" } | complete)
    let has_gitea = ($existing_remotes.stdout | lines | any { |r| ($r | str trim) == "gitea" })

    if $has_gitea {
        warning "Gitea remote already exists — updating URL..."
        run-external "git" "remote" "set-url" "gitea" $resolved_url
        success "Gitea remote URL updated"
    } else {
        info "Adding Gitea remote..."
        run-external "git" "remote" "add" "gitea" $resolved_url
        success "Gitea remote added"
    }

    # Show all remotes
    print ""
    info "Current remotes:"
    let remotes_out = (do { run-external "git" "remote" "-v" } | complete)
    $remotes_out.stdout
    | lines
    | where { |l| $l =~ '^(origin|gitea)' }
    | each { |l| print $"  ($l)" }
    print ""

    # ── Test Gitea connection ─────────────────────────────────────────────────
    heading "Testing Gitea Connection"
    print ""

    info "Testing connection to Gitea repository..."
    let conn = (do { run-external "git" "ls-remote" "gitea" } | complete)
    if $conn.exit_code == 0 {
        success "Successfully connected to Gitea repository!"
    } else {
        warning "Could not connect to Gitea repository."
        print ""
        info "This is normal if the repository does not exist yet."
        print ""
        print "  To create the repository on Gitea:"
        print $"    1. Log in to your Gitea instance"
        print $"    2. Create repository: ($project_name)"
        print "    3. Do NOT initialise with a README"
        print "    4. Run:  just push-gitea"
        print ""
    }

    # ── Push to Gitea ─────────────────────────────────────────────────────────
    heading "Push to Gitea"
    print ""

    let push_reply = (input "Push all branches and tags to Gitea now? (y/N) " | str trim)
    print ""

    if ($push_reply =~ '^[Yy]') {
        info "Pushing all branches to Gitea..."
        let push_all = (do { run-external "git" "push" "gitea" "--all" } | complete)
        if $push_all.exit_code == 0 {
            success "All branches pushed to Gitea"
        } else {
            warning "Failed to push branches (repository might not exist yet)"
        }

        info "Pushing all tags to Gitea..."
        let push_tags = (do { run-external "git" "push" "gitea" "--tags" } | complete)
        if $push_tags.exit_code == 0 {
            success "All tags pushed to Gitea"
        } else {
            warning "Failed to push tags"
        }
    } else {
        info "Skipping push — run 'just push-gitea' when ready."
    }

    # ── Set up .gitea/workflows ───────────────────────────────────────────────
    print ""
    heading "Gitea Actions (CI/CD)"
    print ""

    let gitea_reply = (input "Set up .gitea/workflows from .github/workflows? (y/N) " | str trim)
    print ""

    if ($gitea_reply =~ '^[Yy]') {
        let gitea_dir = ($proj_dir | path join ".gitea" "workflows")

        if ($gitea_dir | path exists) {
            success ".gitea/workflows already exists — skipping copy"
        } else {
            let github_dir = ($proj_dir | path join ".github" "workflows")
            if ($github_dir | path exists) {
                info "Copying workflows from .github/workflows → .gitea/workflows..."
                mkdir $gitea_dir
                let workflow_files = (glob ($github_dir | path join "*.yml"))
                for wf in $workflow_files {
                    let dest = ($gitea_dir | path join ($wf | path basename))
                    cp $wf $dest
                }
                success "Workflows copied to .gitea/workflows/"
                info "Review and adjust them for Gitea Actions syntax if needed."
            } else {
                mkdir $gitea_dir
                success ".gitea/workflows directory created"
                info "Add your workflow YAML files to .gitea/workflows/"
            }
        }
    } else {
        info "Skipping .gitea setup."
    }

    # ── Summary ───────────────────────────────────────────────────────────────
    print ""
    heading "Migration Complete! 🎉"
    print ""
    success $"Project ($project_name) configured for dual GitHub + Gitea hosting!"
    print ""
    info "What was done:"
    print $"  ✓ Gitea remote set to: ($resolved_url)"
    print ""
    info "Quick commands:"
    print $"  ($cyan)just push($reset)              # Push to GitHub only"
    print $"  ($cyan)just push-gitea($reset)        # Push to Gitea only"
    print $"  ($cyan)just push-all($reset)          # Push to both GitHub and Gitea"
    print $"  ($cyan)just push-tags-all($reset)     # Push tags to both remotes"
    print $"  ($cyan)just sync-gitea($reset)        # Force-sync Gitea from GitHub"
    print $"  ($cyan)just remotes($reset)           # Show all configured remotes"
    print ""
    info "Release commands:"
    print $"  ($cyan)just release 0.3.2($reset)         # Release to GitHub"
    print $"  ($cyan)just release-gitea 0.3.2($reset)   # Release to Gitea"
    print $"  ($cyan)just release-all 0.3.2($reset)     # Release to both remotes"
    print ""
    success "Happy dual-hosting! 🚀"
    print ""
}