Commit c2e57dca authored by Mickaël Desfrênes's avatar Mickaël Desfrênes
Browse files

remove support for MaX <0.0.5

parent 7c909b71
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ commandes new, projects et cache-clear qui peuvent être lancées aussi en dehor
		"err.bundle_install_failed":   "échec de l'installation du bundle %s: %w",
		"err.no_latest_release":       "pas de dernière release disponible",
		"err.unknown_version":         "version inconnue",
		"err.unsupported_max_version": "version de MaX non prise en charge: %s (version minimale: %s)",
		"err.server_start_timeout":    "délai dépassé au démarrage du serveur HTTP sur %s:%d",
		"err.invalid_path":            "%s n'est pas un chemin valide",
		"err.invalid_bundle_archive":  "%s n'est pas un bundle",
@@ -222,6 +223,7 @@ which can also be run outside a MaX directory.`,
		"err.bundle_install_failed":   "bundle installation failed for %s: %w",
		"err.no_latest_release":       "no latest release available",
		"err.unknown_version":         "unknown version",
		"err.unsupported_max_version": "unsupported MaX version: %s (minimum: %s)",
		"err.server_start_timeout":    "timeout while starting HTTP server on %s:%d",
		"err.invalid_path":            "%s is not a valid path",
		"err.invalid_bundle_archive":  "%s is not a bundle",
+112 −9
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@ var fallbackReleases []byte
const version = "0.3.3"

const maxConfigFile = "config.xml"
const baseXDistro = "https://files.basex.org/releases/11.7/BaseX117.zip"
const minSupportedMaxVersion = "0.0.5"
const baseXDistro = "https://files.basex.org/releases/12.2/BaseX122.zip"
const saxonDistro = "https://repo1.maven.org/maven2/net/sf/saxon/Saxon-HE/10.8/Saxon-HE-10.8.jar"
const webPort = 8080
const webHost = "127.0.0.1"
@@ -57,7 +58,7 @@ const gitlabAPIReadToken = "glpat-5BCYCid1WaxxBgax-7VW"

const configInitTemplate = `<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://certic.unicaen.fr/max/ns/1.0" env="dev" vocabulary-bundle="max-dumb-xml">
    <version name="0.0.2" url="https://git.unicaen.fr/pdn-certic/max-v2/-/archive/0.0.2/max-v2-0.0.2.zip"/>
    <version name="0.0.5" url="https://git.unicaen.fr/pdn-certic/max-v2/-/archive/0.0.5/max-v2-0.0.5.zip"/>
    <languages>
        <language>fr</language>
        <language>en</language>
@@ -758,6 +759,7 @@ func maxReleases() ([]release, error) {
				if resp.StatusCode >= 200 && resp.StatusCode < 300 {
					body, _ := io.ReadAll(resp.Body)
					if errDecode := json.Unmarshal(body, &releasesData); errDecode == nil {
						releasesData = filterSupportedMaxReleases(releasesData)
						return
					}
				}
@@ -766,7 +768,9 @@ func maxReleases() ([]release, error) {

		if err := json.Unmarshal(fallbackReleases, &releasesData); err != nil {
			releasesErr = err
			return
		}
		releasesData = filterSupportedMaxReleases(releasesData)
	})
	return releasesData, releasesErr
}
@@ -801,6 +805,80 @@ func latestMaxRelease() (*release, error) {
	return maxRelease(releases[0].Name)
}

func filterSupportedMaxReleases(releases []release) []release {
	filtered := make([]release, 0, len(releases))
	for _, r := range releases {
		if isSupportedMaxVersion(r.Name) {
			filtered = append(filtered, r)
		}
	}
	return filtered
}

func isSupportedMaxVersion(raw string) bool {
	return compareVersion(raw, minSupportedMaxVersion) >= 0
}

func compareVersion(left, right string) int {
	lv, okLeft := parseVersion(left)
	rv, okRight := parseVersion(right)
	if !okLeft || !okRight {
		return -1
	}
	for i := 0; i < len(lv) || i < len(rv); i++ {
		leftPart := 0
		if i < len(lv) {
			leftPart = lv[i]
		}
		rightPart := 0
		if i < len(rv) {
			rightPart = rv[i]
		}
		switch {
		case leftPart < rightPart:
			return -1
		case leftPart > rightPart:
			return 1
		}
	}
	return 0
}

func parseVersion(raw string) ([]int, bool) {
	trimmed := strings.TrimSpace(raw)
	if trimmed == "" {
		return nil, false
	}
	if strings.HasPrefix(trimmed, "v") || strings.HasPrefix(trimmed, "V") {
		trimmed = trimmed[1:]
	}
	main := strings.SplitN(trimmed, "-", 2)[0]
	main = strings.SplitN(main, "+", 2)[0]
	parts := strings.Split(main, ".")
	if len(parts) < 3 {
		return nil, false
	}
	out := make([]int, 0, len(parts))
	for _, part := range parts {
		if part == "" {
			return nil, false
		}
		value, err := strconv.Atoi(part)
		if err != nil {
			return nil, false
		}
		out = append(out, value)
	}
	return out, true
}

func displayVersion(raw string) string {
	if strings.TrimSpace(raw) == "" {
		return T("msg.unknown_title")
	}
	return raw
}

func projectsPath() string {
	return filepath.Join(userMaxDir, "projects.json")
}
@@ -956,7 +1034,6 @@ func dirIsMax(directory string) (bool, error) {
			if start.Name.Local == "configuration" {
				for _, a := range start.Attr {
					if a.Name.Local == "xmlns" && a.Value == "http://certic.unicaen.fr/max/ns/1.0" {
						_ = pingProjects(abs, nil)
						return true, nil
					}
				}
@@ -976,8 +1053,31 @@ func checkDirIsMax(directory string) error {
	if !ok {
		return errors.New(T("err.not_max_directory"))
	}
	if err := checkProjectMaxVersionSupported(directory); err != nil {
		return err
	}
	abs, err := filepath.Abs(directory)
	if err != nil {
		return err
	}
	_ = pingProjects(abs, nil)
	return nil
}

func checkProjectMaxVersionSupported(directory string) error {
	abs, err := filepath.Abs(directory)
	if err != nil {
		return err
	}
	config, err := loadProjectConfig(filepath.Join(abs, maxConfigFile))
	if err != nil {
		return err
	}
	if isSupportedMaxVersion(config.Cfg.Version.Name) {
		return nil
	}
	return fmt.Errorf(T("err.unsupported_max_version"), displayVersion(config.Cfg.Version.Name), minSupportedMaxVersion)
}

func ensureAvailableMaxDirectory(directory string) (string, bool, error) {
	if strings.TrimSpace(directory) == "" {
@@ -1446,6 +1546,9 @@ func syncMaxInstance(rootDirectory string, verbose bool) error {
	if err != nil {
		return err
	}
	if !isSupportedMaxVersion(config.Cfg.Version.Name) {
		return fmt.Errorf(T("err.unsupported_max_version"), displayVersion(config.Cfg.Version.Name), minSupportedMaxVersion)
	}

	dotMaxDir := filepath.Join(rootDirectory, ".max")
	if !dirExists(dotMaxDir) || config.maxVersionFromMaxDir() != config.Cfg.Version.Name {
@@ -1485,17 +1588,20 @@ func syncMaxInstance(rootDirectory string, verbose bool) error {
}

func runNew(directory string, interactive bool) error {
	if _, err := ensureJava(); err != nil {
		return err
	}
	rootDirectory, isMax, err := ensureAvailableMaxDirectory(directory)
	if err != nil {
		return err
	}
	if isMax {
		if err := checkProjectMaxVersionSupported(rootDirectory); err != nil {
			return err
		}
		fmt.Println(T("msg.directory_already_max"))
		return nil
	}
	if _, err := ensureJava(); err != nil {
		return err
	}

	var values *initValues
	if interactive {
@@ -2354,9 +2460,6 @@ func formatCommand(cmd *exec.Cmd) string {
}

func runSync(directory string) error {
	if _, err := ensureJava(); err != nil {
		return err
	}
	rootDirectory, isMax, err := ensureAvailableMaxDirectory(directory)
	if err != nil {
		return err
+51 −0
Original line number Diff line number Diff line
@@ -110,6 +110,57 @@ func TestProjectsJSONStorageLifecycle(t *testing.T) {
	}
}

func TestCheckDirIsMaxRejectsUnsupportedMaxVersion(t *testing.T) {
	previousLocale := currentLocale
	setLocale(localeEN)
	t.Cleanup(func() {
		setLocale(previousLocale)
	})

	tmpHome := t.TempDir()
	prevHome := userMaxDir
	userMaxDir = tmpHome
	t.Cleanup(func() {
		userMaxDir = prevHome
	})

	projectDir := filepath.Join(t.TempDir(), "project")
	if err := os.MkdirAll(projectDir, 0o755); err != nil {
		t.Fatal(err)
	}
	config := strings.ReplaceAll(configInitTemplate, "0.0.5", "0.0.4")
	if err := os.WriteFile(filepath.Join(projectDir, maxConfigFile), []byte(config), 0o644); err != nil {
		t.Fatal(err)
	}

	err := checkDirIsMax(projectDir)
	if err == nil {
		t.Fatal("expected unsupported version error")
	}
	if !strings.Contains(err.Error(), "0.0.4") || !strings.Contains(err.Error(), minSupportedMaxVersion) {
		t.Fatalf("expected error to mention configured and minimum versions, got: %v", err)
	}
}

func TestFilterSupportedMaxReleasesDropsVersionsBelowMinimum(t *testing.T) {
	releases := []release{
		{Name: "0.0.6"},
		{Name: "0.0.4"},
		{Name: "v0.0.5"},
		{Name: "invalid"},
	}

	filtered := filterSupportedMaxReleases(releases)
	got := make([]string, 0, len(filtered))
	for _, r := range filtered {
		got = append(got, r.Name)
	}
	want := []string{"0.0.6", "v0.0.5"}
	if strings.Join(got, ",") != strings.Join(want, ",") {
		t.Fatalf("unexpected filtered releases: want %v, got %v", want, got)
	}
}

func TestExtractTarGzPreservesExecutableBit(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("executable permission bits are not relevant on windows")
+1 −1

File changed.

Preview size limit exceeded, changes collapsed.