|
root / src / commands / sync.reef
sync.reef Reef 160 lines 4.5 KB
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 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
108
109
110
111
112
113
114
115
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
148
149
150
151
152
153
154
155
156
157
158
159
/******************************************************************************
               __               ____                __
              / /   ___  ____ _/ __/_____________ _/ /__
             / /   / _ \/ __ `/ /_/ ___/ ___/ __ `/ / _ \
            / /___/  __/ /_/ / __(__  ) /__/ /_/ / /  __/
           /_____/\___/\__,_/_/ /____/\___/\__,_/_/\___/

   (C)opyright 2025, Leafscale, LLC -  https://www.leafscale.com

   Project: Zygaena
  Filename: sync.reef
   Authors: Chris Tusa <chris.tusa@leafscale.com>
   License: <see LICENSE file included with this source code>
Description: Sync command - update ports collection from repository

******************************************************************************/

module commands.sync

import sys.args
import sys.process
import io.dir
import io.path
import io.file
import core.str
import core.config
import core.port
import core.portindex
import util.color
import exitcodes as ec
import core.result as res

export
    fn execute(): int
end export

fn execute(): int
    // Load configuration
    let cfg = config.load()
    let ports_dir = config.get_ports_dir(cfg)

    color.print_action("Syncing ports collection...")
    println("")

    // Check if ports directory exists
    if not dir.dir_exists(ports_dir)
        color.print_error("Ports directory does not exist: " + ports_dir)
        color.print_info("You may need to clone the ports repository first:")
        println("  git clone <ports-repo-url> " + ports_dir)
        return ec.EXIT_CONFIG_ERROR()
    end if

    // Check if it's a git repository
    let git_dir = path.join_path(ports_dir, ".git")
    if not dir.dir_exists(git_dir)
        color.print_warning("Ports directory is not a git repository")
        color.print_info("Cannot sync - no version control detected")
        return ec.EXIT_CONFIG_ERROR()
    end if

    // Run git pull
    color.print_info("Updating from remote repository...")

    let cmd = "cd \"" + ports_dir + "\" && git pull"
    let pid = process.process_spawn_shell(cmd)

    if pid < 0
        color.print_error("Failed to start git pull")
        return ec.EXIT_REPO_UNREACHABLE()
    end if

    let exit_code = process.process_wait(pid)

    if exit_code == 0
        color.print_success("Ports collection updated successfully")

        // Rebuild ports index after successful sync
        portindex.rebuild_port_index()

        // Show summary of changes
        show_update_summary(ports_dir)
        return ec.EXIT_SUCCESS()
    else
        color.print_error("Git pull failed with exit code " + int_to_str(exit_code))
        color.print_info("Check your network connection and repository access")
        return ec.EXIT_REPO_UNREACHABLE()
    end if
end execute

proc show_update_summary(ports_dir: string)
    // Count ports in each category (dynamically discovered)
    mut cats: [string] = new [string](32)
    let cat_count = port.get_categories(cats, 32)

    mut total = 0
    mut i = 0
    while i < cat_count
        let cat = cats[i]
        let cat_path = path.join_path(ports_dir, cat)

        if dir.dir_exists(cat_path)
            let entries = res.unwrap_or(dir.list_dir(cat_path), new [string](0))
            let count = entries.length()

            // Count valid ports (directories with package.toml)
            mut port_count = 0
            mut j = 0
            while j < count
                let entry = entries[j]
                if str.length(entry) > 0 and entry[0] != '.'
                    let toml_path = path.join_path(path.join_path(cat_path, entry), "package.toml")
                    if file.fileExists(toml_path)
                        port_count = port_count + 1
                    end if
                end if
                j = j + 1
            end while

            if port_count > 0
                println("  " + cat + ": " + int_to_str(port_count) + " ports")
                total = total + port_count
            end if
        end if

        i = i + 1
    end while

    println("")
    color.print_info("Total: " + int_to_str(total) + " ports available")
end show_update_summary

// Helper: convert int to string
fn int_to_str(n: int): string
    if n == 0
        return "0"
    end if

    mut negative = false
    mut value = n
    if n < 0
        negative = true
        value = 0 - n
    end if

    mut result = ""
    while value > 0
        let digit = value % 10
        result = str.concat(str.substring("0123456789", digit, 1), result)
        value = value / 10
    end while

    if negative
        result = str.concat("-", result)
    end if

    return result
end int_to_str

end module