工具 API
pkg/utils
包为整个 NuGet Config Parser 库中使用的文件操作、路径操作和 XML 处理提供工具函数。
概述
工具 API 提供:
- 文件系统操作和检查
- 跨平台路径操作
- XML 处理工具
- 字符串和数据验证辅助函数
文件系统操作
FileExists
go
func FileExists(filePath string) bool
检查文件是否存在且不是目录。
参数:
filePath
(string): 要检查的文件路径
返回值:
bool
: 如果文件存在且不是目录则为 true,否则为 false
示例:
go
import "github.com/scagogogo/nuget-config-parser/pkg/utils"
configPath := "/path/to/NuGet.Config"
if utils.FileExists(configPath) {
fmt.Printf("配置文件存在: %s\n", configPath)
// 继续解析...
} else {
fmt.Printf("配置文件未找到: %s\n", configPath)
// 创建默认配置...
}
DirExists
go
func DirExists(dirPath string) bool
检查目录是否存在。
参数:
dirPath
(string): 要检查的目录路径
返回值:
bool
: 如果目录存在则为 true,否则为 false
示例:
go
configDir := "/etc/nuget"
if utils.DirExists(configDir) {
fmt.Printf("配置目录存在: %s\n", configDir)
} else {
fmt.Printf("创建配置目录: %s\n", configDir)
err := os.MkdirAll(configDir, 0755)
if err != nil {
log.Fatalf("创建目录失败: %v", err)
}
}
IsReadableFile
go
func IsReadableFile(filePath string) bool
检查文件是否存在且可读。
参数:
filePath
(string): 要检查的文件路径
返回值:
bool
: 如果文件存在且可读则为 true,否则为 false
示例:
go
configPath := "/path/to/NuGet.Config"
if utils.IsReadableFile(configPath) {
// 安全读取文件
content, err := os.ReadFile(configPath)
if err != nil {
log.Printf("读取文件错误: %v", err)
}
} else {
fmt.Printf("文件不可读: %s\n", configPath)
}
IsWritableFile
go
func IsWritableFile(filePath string) bool
检查文件是否可写(或如果不存在,目录是否可写)。
参数:
filePath
(string): 要检查的文件路径
返回值:
bool
: 如果文件可写则为 true,否则为 false
示例:
go
configPath := "/path/to/NuGet.Config"
if utils.IsWritableFile(configPath) {
// 安全写入文件
err := os.WriteFile(configPath, []byte("content"), 0644)
if err != nil {
log.Printf("写入文件错误: %v", err)
}
} else {
fmt.Printf("文件不可写: %s\n", configPath)
}
路径操作
IsAbsolutePath
go
func IsAbsolutePath(path string) bool
检查路径是否为绝对路径。
参数:
path
(string): 要检查的路径
返回值:
bool
: 如果路径是绝对路径则为 true,相对路径则为 false
示例:
go
// Unix/Linux 示例
fmt.Println(utils.IsAbsolutePath("/etc/nuget")) // true
fmt.Println(utils.IsAbsolutePath("./config")) // false
fmt.Println(utils.IsAbsolutePath("../config")) // false
// Windows 示例
fmt.Println(utils.IsAbsolutePath("C:\\nuget\\config")) // true
fmt.Println(utils.IsAbsolutePath(".\\config")) // false
NormalizePath
go
func NormalizePath(path string) string
通过清理路径并转换为操作系统特定格式来规范化文件路径。
参数:
path
(string): 要规范化的路径
返回值:
string
: 规范化的路径
示例:
go
// 清理冗余路径元素
messyPath := "/etc/nuget/../nuget/./config"
cleanPath := utils.NormalizePath(messyPath)
fmt.Printf("规范化: %s\n", cleanPath)
// 输出: /etc/nuget/config
// 处理不同的分隔符
mixedPath := "/etc\\nuget/config"
normalizedPath := utils.NormalizePath(mixedPath)
fmt.Printf("规范化: %s\n", normalizedPath)
JoinPaths
go
func JoinPaths(basePath string, paths ...string) string
使用操作系统特定的路径分隔符连接多个路径元素。
参数:
basePath
(string): 基础路径paths
(...string): 要连接的附加路径元素
返回值:
string
: 连接的路径
示例:
go
// 连接路径元素
basePath := "/etc"
configPath := utils.JoinPaths(basePath, "nuget", "NuGet.Config")
fmt.Printf("连接的路径: %s\n", configPath)
// 输出: /etc/nuget/NuGet.Config
// Windows 示例
winBase := "C:\\Users"
winPath := utils.JoinPaths(winBase, "username", ".nuget", "packages")
fmt.Printf("Windows 路径: %s\n", winPath)
// 输出: C:\Users\username\.nuget\packages
// 处理尾随斜杠
trailingSlash := "/home/user/"
result := utils.JoinPaths(trailingSlash, "nuget", "packages")
fmt.Printf("结果: %s\n", result)
// 输出: /home/user/nuget/packages
ResolvePath
go
func ResolvePath(basePath, path string) string
相对于基础路径解析路径。如果路径已经是绝对路径,则返回规范化的路径。
参数:
basePath
(string): 解析相对路径的基础路径path
(string): 要解析的路径(可以是相对或绝对)
返回值:
string
: 解析的绝对路径
示例:
go
basePath := "/etc/nuget"
// 解析相对路径
relativePath := "../packages/cache"
resolvedRelative := utils.ResolvePath(basePath, relativePath)
fmt.Printf("相对路径 '%s' 解析为: %s\n", relativePath, resolvedRelative)
// 输出: 相对路径 '../packages/cache' 解析为: /etc/packages/cache
// 处理绝对路径
absolutePath := "/var/nuget/packages"
resolvedAbsolute := utils.ResolvePath(basePath, absolutePath)
fmt.Printf("绝对路径 '%s' 保持: %s\n", absolutePath, resolvedAbsolute)
// 输出: 绝对路径 '/var/nuget/packages' 保持: /var/nuget/packages
ExpandEnvVars
go
func ExpandEnvVars(path string) string
展开路径字符串中的环境变量。
参数:
path
(string): 包含环境变量的路径
返回值:
string
: 展开环境变量后的路径
支持的格式:
- Unix/Linux/macOS:
$VAR
或${VAR}
- Windows:
%VAR%
示例:
go
// Unix/Linux/macOS 示例
unixPath := "$HOME/.nuget/packages"
expandedUnixPath := utils.ExpandEnvVars(unixPath)
fmt.Printf("展开: %s\n", expandedUnixPath)
// 输出: 展开: /home/user/.nuget/packages
bracedPath := "${HOME}/.config/NuGet/NuGet.Config"
expandedBracedPath := utils.ExpandEnvVars(bracedPath)
fmt.Printf("展开: %s\n", expandedBracedPath)
// Windows 示例
winPath := "%USERPROFILE%\\.nuget\\packages"
expandedWinPath := utils.ExpandEnvVars(winPath)
fmt.Printf("展开: %s\n", expandedWinPath)
// 输出: 展开: C:\Users\username\.nuget\packages
XML 处理
ValidateXML
go
func ValidateXML(content []byte) error
验证内容是否为格式良好的 XML。
参数:
content
([]byte): 要验证的 XML 内容
返回值:
error
: 如果 XML 格式不正确则返回错误,有效则为 nil
示例:
go
// 有效 XML
validXML := []byte(`<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>`)
err := utils.ValidateXML(validXML)
if err != nil {
fmt.Printf("无效 XML: %v\n", err)
} else {
fmt.Println("XML 有效")
}
// 无效 XML
invalidXML := []byte(`<configuration><packageSources><add key="test"`)
err = utils.ValidateXML(invalidXML)
if err != nil {
fmt.Printf("无效 XML: %v\n", err)
}
FormatXML
go
func FormatXML(content []byte) ([]byte, error)
使用适当的缩进格式化 XML 内容。
参数:
content
([]byte): 要格式化的 XML 内容
返回值:
[]byte
: 格式化的 XML 内容error
: 格式化失败时的错误
示例:
go
// 未格式化的 XML
unformattedXML := []byte(`<configuration><packageSources><add key="nuget.org" value="https://api.nuget.org/v3/index.json" /></packageSources></configuration>`)
formattedXML, err := utils.FormatXML(unformattedXML)
if err != nil {
log.Printf("格式化 XML 失败: %v", err)
} else {
fmt.Println("格式化的 XML:")
fmt.Println(string(formattedXML))
}
// 输出:
// <?xml version="1.0" encoding="UTF-8"?>
// <configuration>
// <packageSources>
// <add key="nuget.org" value="https://api.nuget.org/v3/index.json"/>
// </packageSources>
// </configuration>
ExtractXMLElement
go
func ExtractXMLElement(content []byte, elementName string) ([]byte, error)
从内容中提取特定的 XML 元素。
参数:
content
([]byte): 要搜索的 XML 内容elementName
(string): 要提取的元素名称
返回值:
[]byte
: 提取的元素内容error
: 未找到元素或提取失败时的错误
示例:
go
xmlContent := []byte(`<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="local" value="/path/to/local" />
</packageSources>
<config>
<add key="globalPackagesFolder" value="/packages" />
</config>
</configuration>`)
// 提取 packageSources 元素
packageSources, err := utils.ExtractXMLElement(xmlContent, "packageSources")
if err != nil {
log.Printf("提取元素失败: %v", err)
} else {
fmt.Println("包源:")
fmt.Println(string(packageSources))
}
字符串工具
IsEmptyOrWhitespace
go
func IsEmptyOrWhitespace(s string) bool
检查字符串是否为空或仅包含空白字符。
参数:
s
(string): 要检查的字符串
返回值:
bool
: 如果字符串为空或仅包含空白字符则为 true
示例:
go
fmt.Println(utils.IsEmptyOrWhitespace("")) // true
fmt.Println(utils.IsEmptyOrWhitespace(" ")) // true
fmt.Println(utils.IsEmptyOrWhitespace("\t\n")) // true
fmt.Println(utils.IsEmptyOrWhitespace("content")) // false
fmt.Println(utils.IsEmptyOrWhitespace(" content ")) // false
TrimWhitespace
go
func TrimWhitespace(s string) string
从字符串中修剪前导和尾随空白字符。
参数:
s
(string): 要修剪的字符串
返回值:
string
: 修剪后的字符串
示例:
go
input := " \t content with spaces \n "
trimmed := utils.TrimWhitespace(input)
fmt.Printf("修剪后: '%s'\n", trimmed)
// 输出: 修剪后: 'content with spaces'
SanitizeXMLValue
go
func SanitizeXMLValue(value string) string
清理字符串值以在 XML 属性或内容中安全使用。
参数:
value
(string): 要清理的值
返回值:
string
: 对 XML 安全的清理值
示例:
go
unsafeValue := `value with "quotes" & <brackets>`
safeValue := utils.SanitizeXMLValue(unsafeValue)
fmt.Printf("清理后: %s\n", safeValue)
// 输出: 清理后: value with "quotes" & <brackets>
验证工具
IsValidURL
go
func IsValidURL(urlStr string) bool
验证字符串是否为有效的 URL。
参数:
urlStr
(string): 要验证的 URL 字符串
返回值:
bool
: 如果 URL 有效则为 true
示例:
go
validURLs := []string{
"https://api.nuget.org/v3/index.json",
"http://localhost:8080/nuget",
"file:///path/to/packages",
}
invalidURLs := []string{
"not-a-url",
"://missing-scheme",
"https://",
}
for _, url := range validURLs {
if utils.IsValidURL(url) {
fmt.Printf("有效 URL: %s\n", url)
}
}
for _, url := range invalidURLs {
if !utils.IsValidURL(url) {
fmt.Printf("无效 URL: %s\n", url)
}
}
IsValidPackageSourceKey
go
func IsValidPackageSourceKey(key string) bool
验证字符串是否为有效的包源键。
参数:
key
(string): 要验证的包源键
返回值:
bool
: 如果键有效则为 true
验证规则:
- 不为空或仅包含空白字符
- 仅包含字母数字字符、连字符、下划线和点
- 不以特殊字符开头或结尾
示例:
go
validKeys := []string{
"nuget.org",
"company-feed",
"local_packages",
"feed123",
}
invalidKeys := []string{
"",
" ",
"invalid key with spaces",
"-starts-with-dash",
"ends-with-dash-",
"has@invalid#chars",
}
for _, key := range validKeys {
if utils.IsValidPackageSourceKey(key) {
fmt.Printf("有效键: %s\n", key)
}
}
for _, key := range invalidKeys {
if !utils.IsValidPackageSourceKey(key) {
fmt.Printf("无效键: '%s'\n", key)
}
}
完整使用示例
go
package main
import (
"fmt"
"log"
"os"
"github.com/scagogogo/nuget-config-parser/pkg/utils"
)
func main() {
// 文件操作
configPath := "/path/to/NuGet.Config"
if utils.FileExists(configPath) {
fmt.Printf("配置文件存在: %s\n", configPath)
if utils.IsReadableFile(configPath) {
content, err := os.ReadFile(configPath)
if err != nil {
log.Printf("读取文件错误: %v", err)
return
}
// 验证 XML
if err := utils.ValidateXML(content); err != nil {
log.Printf("无效 XML: %v", err)
return
}
// 格式化 XML
formatted, err := utils.FormatXML(content)
if err != nil {
log.Printf("格式化 XML 失败: %v", err)
} else {
fmt.Println("格式化的 XML:")
fmt.Println(string(formatted))
}
}
} else {
fmt.Printf("配置文件未找到: %s\n", configPath)
// 如果需要创建目录
configDir := utils.JoinPaths("/etc", "nuget")
if !utils.DirExists(configDir) {
fmt.Printf("创建目录: %s\n", configDir)
err := os.MkdirAll(configDir, 0755)
if err != nil {
log.Fatalf("创建目录失败: %v", err)
}
}
}
// 路径操作
basePath := "/etc/nuget"
relativePath := "../packages"
resolvedPath := utils.ResolvePath(basePath, relativePath)
fmt.Printf("解析的路径: %s\n", resolvedPath)
// 环境变量展开
envPath := "$HOME/.nuget/packages"
expandedPath := utils.ExpandEnvVars(envPath)
fmt.Printf("展开的路径: %s\n", expandedPath)
// 验证
testURL := "https://api.nuget.org/v3/index.json"
if utils.IsValidURL(testURL) {
fmt.Printf("有效 URL: %s\n", testURL)
}
testKey := "nuget.org"
if utils.IsValidPackageSourceKey(testKey) {
fmt.Printf("有效包源键: %s\n", testKey)
}
}
最佳实践
- 检查文件存在性: 在尝试文件操作之前始终使用
FileExists()
- 验证输入: 在处理之前使用验证函数检查 URL 和键
- 正确处理路径: 使用路径操作函数实现跨平台兼容性
- 清理 XML 内容: 对用户提供的内容使用
SanitizeXMLValue()
- 验证 XML: 在解析之前使用
ValidateXML()
尽早捕获格式错误的内容 - 规范化路径: 使用
NormalizePath()
清理路径字符串 - 展开环境变量: 使用
ExpandEnvVars()
实现灵活的路径配置
线程安全
此包中的所有工具函数都是线程安全的,可以并发使用。