2022-05-05 13:25:50 +00:00
|
|
|
// Copyright 2022 Cloudbase Solutions SRL
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
|
// not use this file except in compliance with the License. You may obtain
|
|
|
|
|
// a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
|
// License for the specific language governing permissions and limitations
|
|
|
|
|
// under the License.
|
|
|
|
|
|
2022-04-15 15:22:47 +00:00
|
|
|
package util
|
|
|
|
|
|
|
|
|
|
import (
|
2022-04-22 14:46:27 +00:00
|
|
|
"context"
|
2025-08-16 19:31:58 +00:00
|
|
|
"fmt"
|
2024-03-17 10:21:41 +00:00
|
|
|
"net/http"
|
2025-08-12 09:28:21 +00:00
|
|
|
"unicode/utf8"
|
2022-04-15 15:22:47 +00:00
|
|
|
|
2024-03-17 11:07:44 +00:00
|
|
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
2025-04-04 20:44:57 +00:00
|
|
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
2024-02-22 07:31:51 +01:00
|
|
|
"github.com/cloudbase/garm/runner/common"
|
2022-04-18 17:26:13 +00:00
|
|
|
)
|
|
|
|
|
|
2025-04-04 20:44:57 +00:00
|
|
|
func FetchTools(ctx context.Context, cli common.GithubClient) ([]commonParams.RunnerApplicationDownload, error) {
|
|
|
|
|
tools, ghResp, err := cli.ListEntityRunnerApplicationDownloads(ctx)
|
2024-03-17 10:21:41 +00:00
|
|
|
if err != nil {
|
2025-04-04 20:44:57 +00:00
|
|
|
if ghResp != nil && ghResp.StatusCode == http.StatusUnauthorized {
|
2025-08-16 19:31:58 +00:00
|
|
|
return nil, fmt.Errorf("error fetching tools: %w", runnerErrors.ErrUnauthorized)
|
2024-03-17 10:21:41 +00:00
|
|
|
}
|
2025-08-16 19:31:58 +00:00
|
|
|
return nil, fmt.Errorf("error fetching runner tools: %w", err)
|
2024-03-17 10:21:41 +00:00
|
|
|
}
|
|
|
|
|
|
2025-04-04 20:44:57 +00:00
|
|
|
ret := []commonParams.RunnerApplicationDownload{}
|
|
|
|
|
for _, tool := range tools {
|
|
|
|
|
if tool == nil {
|
|
|
|
|
continue
|
2024-03-17 10:21:41 +00:00
|
|
|
}
|
2025-04-04 20:44:57 +00:00
|
|
|
ret = append(ret, commonParams.RunnerApplicationDownload(*tool))
|
2023-08-15 17:19:06 +00:00
|
|
|
}
|
2025-04-04 20:44:57 +00:00
|
|
|
return ret, nil
|
2022-04-22 14:46:27 +00:00
|
|
|
}
|
2025-08-12 09:28:21 +00:00
|
|
|
|
|
|
|
|
func ASCIIEqualFold(s, t string) bool {
|
|
|
|
|
// Fast ASCII path for equal-length ASCII strings
|
|
|
|
|
if len(s) == len(t) && isASCII(s) && isASCII(t) {
|
|
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
|
a, b := s[i], t[i]
|
|
|
|
|
if a != b {
|
|
|
|
|
if 'A' <= a && a <= 'Z' {
|
|
|
|
|
a = a + 'a' - 'A'
|
|
|
|
|
}
|
|
|
|
|
if 'A' <= b && b <= 'Z' {
|
|
|
|
|
b = b + 'a' - 'A'
|
|
|
|
|
}
|
|
|
|
|
if a != b {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UTF-8 path - handle different byte lengths correctly
|
|
|
|
|
i, j := 0, 0
|
|
|
|
|
for i < len(s) && j < len(t) {
|
|
|
|
|
sr, sizeS := utf8.DecodeRuneInString(s[i:])
|
|
|
|
|
tr, sizeT := utf8.DecodeRuneInString(t[j:])
|
|
|
|
|
|
|
|
|
|
// Handle invalid UTF-8 - they must be identical
|
|
|
|
|
if sr == utf8.RuneError || tr == utf8.RuneError {
|
|
|
|
|
// For invalid UTF-8, compare the raw bytes
|
|
|
|
|
if sr == utf8.RuneError && tr == utf8.RuneError {
|
|
|
|
|
if sizeS == sizeT && s[i:i+sizeS] == t[j:j+sizeT] {
|
|
|
|
|
i += sizeS
|
|
|
|
|
j += sizeT
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if sr != tr {
|
|
|
|
|
// Apply ASCII case folding only
|
|
|
|
|
if 'A' <= sr && sr <= 'Z' {
|
|
|
|
|
sr = sr + 'a' - 'A'
|
|
|
|
|
}
|
|
|
|
|
if 'A' <= tr && tr <= 'Z' {
|
|
|
|
|
tr = tr + 'a' - 'A'
|
|
|
|
|
}
|
|
|
|
|
if sr != tr {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i += sizeS
|
|
|
|
|
j += sizeT
|
|
|
|
|
}
|
|
|
|
|
return i == len(s) && j == len(t)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isASCII(s string) bool {
|
|
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
|
if s[i] >= 0x80 {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|