本文整理汇总了Golang中github.com/blang/semver.Parse函数的典型用法代码示例。如果您正苦于以下问题:Golang Parse函数的具体用法?Golang Parse怎么用?Golang Parse使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了Parse函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: ParseImageTag
// ParseImageTag parses the docker image tag string and returns a validated Version or error
func ParseImageTag(s string) (CombinedVersion, error) {
// try parse as a SEMVER
prefix := ""
version, err := semver.Parse(s)
if err == nil {
return CombinedVersion{Prefix: prefix, Version: version}, nil
}
// accept format such as `vSEMVER`
if vIndex := strings.IndexRune(s, 'v'); vIndex == 0 {
prefix = s[:vIndex+1]
version, err = semver.Parse(s[vIndex+1:])
if err == nil {
return CombinedVersion{Prefix: prefix, Version: version}, nil
}
}
// accept format such as `ANY-SEMVER`
if firstHyphenIndex := strings.IndexRune(s, '-'); firstHyphenIndex != -1 {
prefix = s[:firstHyphenIndex+1]
version, err = semver.Parse(s[firstHyphenIndex+1:])
if err == nil {
return CombinedVersion{Prefix: prefix, Version: version}, nil
}
}
return CombinedVersion{}, err
}
开发者ID:aclisp,项目名称:kubecon,代码行数:26,代码来源:algorithm.go
示例2: UnmarshalJSON
// UnmarshalJSON implements json.Unmarshaler and postprocesses of ProducerTopics and VersionObj
func (p *Producer) UnmarshalJSON(b []byte) error {
var r struct {
RemoteAddress string `json:"remote_address"`
Hostname string `json:"hostname"`
BroadcastAddress string `json:"broadcast_address"`
TCPPort int `json:"tcp_port"`
HTTPPort int `json:"http_port"`
Version string `json:"version"`
Topics []string `json:"topics"`
Tombstoned []bool `json:"tombstones"`
}
if err := json.Unmarshal(b, &r); err != nil {
return err
}
*p = Producer{
RemoteAddress: r.RemoteAddress,
Hostname: r.Hostname,
BroadcastAddress: r.BroadcastAddress,
TCPPort: r.TCPPort,
HTTPPort: r.HTTPPort,
Version: r.Version,
}
for i, t := range r.Topics {
p.Topics = append(p.Topics, ProducerTopic{Topic: t, Tombstoned: r.Tombstoned[i]})
}
version, err := semver.Parse(p.Version)
if err != nil {
version, _ = semver.Parse("0.0.0")
}
p.VersionObj = version
return nil
}
开发者ID:nsqio,项目名称:nsq,代码行数:33,代码来源:types.go
示例3: ToValidSemver
// ToValidSemver attempts to return the input as valid semver.
// If the input fails to parse as semver, it appends .0 or .0.0 to the input and retries
// If this is still not valid semver, it returns an error
func (s SemverConverter) ToValidSemver(input string) (semver.Version, error) {
v, err := semver.Parse(input)
if err == nil {
return v, nil
}
s.logger.Info(fmt.Sprintf(
"failed to parse semver: '%s', appending zeros and trying again",
input,
))
maybeSemver := input
segs := strings.SplitN(maybeSemver, ".", 3)
switch len(segs) {
case 2:
maybeSemver += ".0"
case 1:
maybeSemver += ".0.0"
}
v, err = semver.Parse(maybeSemver)
if err == nil {
return v, nil
}
s.logger.Info(fmt.Sprintf(
"still failed to parse semver: '%s', giving up",
maybeSemver,
))
return semver.Version{}, err
}
开发者ID:pivotal-cf-experimental,项目名称:pivnet-resource,代码行数:35,代码来源:semver.go
示例4: PrioritizeTags
// PrioritizeTags orders a set of image tags with a few conventions:
//
// 1. the "latest" tag, if present, should be first
// 2. any tags that represent a semantic major version ("5", "v5") should be next, in descending order
// 3. any tags that represent a semantic minor version ("5.1", "v5.1") should be next, in descending order
// 4. any tags that represent a full semantic version ("5.1.3-other", "v5.1.3-other") should be next, in descending order
// 5. any remaining tags should be sorted in lexicographic order
//
// The method updates the tags in place.
func PrioritizeTags(tags []string) {
remaining := tags
finalTags := make([]string, 0, len(tags))
for i, tag := range tags {
if tag == DefaultImageTag {
tags[0], tags[i] = tags[i], tags[0]
finalTags = append(finalTags, tags[0])
remaining = tags[1:]
break
}
}
exact := make(map[string]string)
var major, minor, micro semver.Versions
other := make([]string, 0, len(remaining))
for _, tag := range remaining {
short := strings.TrimLeft(tag, "v")
v, err := semver.Parse(short)
switch {
case err == nil:
exact[v.String()] = tag
micro = append(micro, v)
continue
case reMajorSemantic.MatchString(short):
if v, err = semver.Parse(short + ".0.0"); err == nil {
exact[v.String()] = tag
major = append(major, v)
continue
}
case reMinorSemantic.MatchString(short):
if v, err = semver.Parse(short + ".0"); err == nil {
exact[v.String()] = tag
minor = append(minor, v)
continue
}
}
other = append(other, tag)
}
sort.Sort(sort.Reverse(major))
sort.Sort(sort.Reverse(minor))
sort.Sort(sort.Reverse(micro))
sort.Sort(sort.StringSlice(other))
for _, v := range major {
finalTags = append(finalTags, exact[v.String()])
}
for _, v := range minor {
finalTags = append(finalTags, exact[v.String()])
}
for _, v := range micro {
finalTags = append(finalTags, exact[v.String()])
}
for _, v := range other {
finalTags = append(finalTags, v)
}
copy(tags, finalTags)
}
开发者ID:tracyrankin,项目名称:origin,代码行数:65,代码来源:helper.go
示例5: Less
func (r releases) Less(i, j int) bool {
v1, err := semver.Parse(r[i].Version)
if err != nil {
panic(err)
}
v2, err := semver.Parse(r[j].Version)
if err != nil {
writeLn(r[j].Version)
panic(err)
}
return v1.LT(v2)
}
开发者ID:gernest,项目名称:goo,代码行数:12,代码来源:models.go
示例6: Version
// Version returns the Docker version and whether it is a Red Hat distro version
func (h *Helper) Version() (*semver.Version, bool, error) {
glog.V(5).Infof("Retrieving Docker version")
env, err := h.client.Version()
if err != nil {
glog.V(2).Infof("Error retrieving version: %v", err)
return nil, false, err
}
glog.V(5).Infof("Docker version results: %#v", env)
versionStr := env.Get("Version")
if len(versionStr) == 0 {
return nil, false, errors.New("did not get a version")
}
glog.V(5).Infof("Version: %s", versionStr)
dockerVersion, err := semver.Parse(versionStr)
if err != nil {
glog.V(2).Infof("Error parsing Docker version %q", versionStr)
return nil, false, err
}
isRedHat := false
packageVersion := env.Get("PkgVersion")
if len(packageVersion) > 0 {
isRedHat = fedoraPackage.MatchString(packageVersion) || rhelPackage.MatchString(packageVersion)
}
return &dockerVersion, isRedHat, nil
}
开发者ID:juanluisvaladas,项目名称:origin,代码行数:26,代码来源:helper.go
示例7: FromSource
func FromSource(source models.Source) (Driver, error) {
var initialVersion semver.Version
if source.InitialVersion != "" {
version, err := semver.Parse(source.InitialVersion)
if err != nil {
return nil, fmt.Errorf("invalid initial version (%s): %s", source.InitialVersion, err)
}
initialVersion = version
} else {
initialVersion = semver.Version{Major: 0, Minor: 0, Patch: 0}
}
switch source.Driver {
case models.DriverUnspecified, models.DriverS3:
auth := aws.Auth{
AccessKey: source.AccessKeyID,
SecretKey: source.SecretAccessKey,
}
regionName := source.RegionName
if len(regionName) == 0 {
regionName = aws.USEast.Name
}
region, ok := aws.Regions[regionName]
if !ok {
return nil, errors.New(fmt.Sprintf("no such region '%s'", regionName))
}
if len(source.Endpoint) != 0 {
region = aws.Region{
S3Endpoint: fmt.Sprintf("https://%s", source.Endpoint),
}
}
client := s3.New(auth, region)
bucket := client.Bucket(source.Bucket)
return &S3Driver{
InitialVersion: initialVersion,
Bucket: bucket,
Key: source.Key,
}, nil
case models.DriverGit:
return &GitDriver{
InitialVersion: initialVersion,
URI: source.URI,
Branch: source.Branch,
PrivateKey: source.PrivateKey,
File: source.File,
}, nil
default:
return nil, fmt.Errorf("unknown driver: %s", source.Driver)
}
}
开发者ID:xtreme-sameer-vohra,项目名称:semver-resource,代码行数:60,代码来源:driver.go
示例8: checkSchema
func checkSchema() {
var count int
defer writeConstants()
db.DB.Table("constants").Where("schema_version = ?", schemaVersion.String()).Count(&count)
if count == 1 {
return
}
currStr := getCurrConstants().SchemaVersion
if currStr == "" {
db.DB.Save(&Constant{
schemaVersion.String(),
})
//Initial database migration
whitelist_id_string()
//Write current schema version
return
}
if v, _ := semver.Parse(currStr); v.Major < schemaVersion.Major {
logrus.Warningf("Incompatible schema change detected (%s), attempting to migrate to (%s).", currStr, schemaVersion.String())
for i := v.Major + 1; i <= schemaVersion.Major; i++ {
logrus.Debugf("Calling migration routine for %d.0.0", i)
f := migrationRoutines[i]
f()
}
}
}
开发者ID:gpittarelli,项目名称:Helen,代码行数:30,代码来源:changes.go
示例9: getLatestVersion
func getLatestVersion(zipFile []byte, prefix, suffix string) (string, error) {
r, err := zip.NewReader(bytes.NewReader(zipFile), int64(len(zipFile)))
if err != nil {
return "", err
}
latest := ""
for _, f := range r.File {
artifact := path.Base(f.Name)
if strings.HasPrefix(artifact, prefix) && strings.HasSuffix(artifact, suffix) {
v := extractVersion(artifact)
if latest == "" {
latest = v
}
v1, err := semver.Parse(v)
if err != nil {
return "", err
}
l := semver.MustParse(latest)
if v1.GT(l) {
latest = v
}
}
}
return latest, nil
}
开发者ID:fikridroid,项目名称:gradleplease,代码行数:25,代码来源:get_versions.go
示例10: mustParse
func mustParse(s string) semver.Version {
v, err := semver.Parse(s)
if err != nil {
panic(`semver: Parse(` + s + `): ` + err.Error())
}
return v
}
开发者ID:shlomimatichin,项目名称:useragent,代码行数:7,代码来源:parse_test.go
示例11: bumpedVersion
// bumpedVersion returns new bumped-up version according to given spec.
func (conf Config) bumpedVersion(version string) (string, error) {
if conf.Exact != "" {
exact, err := semver.New(conf.Exact)
if err != nil {
return "", err
}
return exact.String(), nil
}
v, err := semver.Parse(version)
if err != nil {
return "", err
}
if conf.MajorDelta > 0 {
v.Major = v.Major + conf.MajorDelta
v.Minor = 0
v.Patch = 0
} else if conf.MinorDelta > 0 {
v.Minor = v.Minor + conf.MinorDelta
v.Patch = 0
} else if conf.PatchDelta > 0 {
v.Patch = v.Patch + conf.PatchDelta
}
return v.String(), nil
}
开发者ID:motemen,项目名称:gobump,代码行数:29,代码来源:gobump.go
示例12: Parse
func Parse(versionString string) (*Version, error) {
v, err := semver.Parse(versionString)
if err != nil {
return nil, err
}
return &Version{v}, nil
}
开发者ID:salsaflow,项目名称:salsaflow,代码行数:7,代码来源:version.go
示例13: Parse
// Parse will try to parse the data and determine which specific version of schema to further parse.
func (parser YAMLParser) Parse(data []byte) (common.OpenControl, error) {
if data == nil || len(data) == 0 {
return nil, common.ErrNoDataToParse
}
b := Base{}
err := yaml.Unmarshal(data, &b)
if err != nil {
return nil, errors.New(ErrMalformedBaseYamlPrefix + " - " + err.Error())
}
var opencontrol common.OpenControl
var parseError error
v, err := semver.Parse(b.SchemaVersion)
if err != nil {
return nil, common.ErrCantParseSemver
}
switch {
case SchemaV1_0_0.Equals(v):
opencontrol = new(v1_0_0.OpenControl)
parseError = yaml.Unmarshal(data, opencontrol)
default:
return nil, common.ErrUnknownSchemaVersion
}
if parseError != nil {
return nil, parseError
}
return opencontrol, nil
}
开发者ID:opencontrol,项目名称:compliance-masonry,代码行数:30,代码来源:parse.go
示例14: GetLookupdProducers
// GetLookupdProducers returns a ProducerList metadata for each node connected to the given lookupds
func (c *ClusterInfo) GetLookupdProducers(lookupdHTTPAddrs []string) (ProducerList, error) {
var success bool
var output []*Producer
var lock sync.Mutex
var wg sync.WaitGroup
allProducers := make(map[string]*Producer)
maxVersion, _ := semver.Parse("0.0.0")
type respType struct {
Producers []*Producer `json:"producers"`
}
for _, addr := range lookupdHTTPAddrs {
wg.Add(1)
endpoint := fmt.Sprintf("http://%s/nodes", addr)
c.logf("LOOKUPD: querying %s", endpoint)
go func(addr string, endpoint string) {
defer wg.Done()
var resp respType
err := http_api.NegotiateV1(endpoint, &resp)
if err != nil {
c.logf("ERROR: lookupd %s - %s", endpoint, err)
return
}
lock.Lock()
defer lock.Unlock()
success = true
for _, producer := range resp.Producers {
key := producer.TCPAddress()
p, ok := allProducers[key]
if !ok {
if maxVersion.LT(producer.VersionObj) {
maxVersion = producer.VersionObj
}
sort.Sort(producer.Topics)
p = producer
allProducers[key] = p
output = append(output, p)
}
p.RemoteAddresses = append(p.RemoteAddresses, fmt.Sprintf("%s/%s", addr, producer.Address()))
}
}(addr, endpoint)
}
wg.Wait()
if success == false {
return nil, errors.New("unable to query any lookupd")
}
for _, producer := range allProducers {
if producer.VersionObj.LT(maxVersion) {
producer.OutOfDate = true
}
}
sort.Sort(ProducersByHost{output})
return output, nil
}
开发者ID:myhongkongzhen,项目名称:nsq,代码行数:61,代码来源:data.go
示例15: Parse
// Parse will try to parse the data and determine which specific version of schema to further parse.
func Parse(parser common.SchemaParser, data []byte) (common.BaseSchema, error) {
if data == nil || len(data) == 0 {
return nil, ErrNoDataToParse
}
base := common.Base{}
err := yaml.Unmarshal(data, &base)
if err != nil {
return nil, errors.New(ErrMalformedBaseYamlPrefix + " - " + err.Error())
}
var schema common.BaseSchema
var parseError error
v, err := semver.Parse(base.SchemaVersion)
if err != nil {
return nil, ErrCantParseSemver
}
switch {
case SchemaV1_0_0.Equals(v):
schema, parseError = parser.ParseV1_0_0(data)
default:
return nil, ErrUnknownSchemaVersion
}
if parseError != nil {
return nil, parseError
}
return schema, nil
}
开发者ID:geramirez,项目名称:compliance-masonry,代码行数:29,代码来源:parse.go
示例16: setInitDynamicDefaults
func setInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error {
// Auto-detect the IP
if len(cfg.API.AdvertiseAddresses) == 0 {
ip, err := netutil.ChooseHostInterface()
if err != nil {
return err
}
cfg.API.AdvertiseAddresses = []string{ip.String()}
}
// Validate version argument
ver, err := kubeadmutil.KubernetesReleaseVersion(cfg.KubernetesVersion)
if err != nil {
if cfg.KubernetesVersion != kubeadmapiext.DefaultKubernetesVersion {
return err
} else {
ver = kubeadmapiext.DefaultKubernetesFallbackVersion
}
}
cfg.KubernetesVersion = ver
fmt.Println("[init] Using Kubernetes version:", ver)
// Omit the "v" in the beginning, otherwise semver will fail
// If the version is newer than the specified version, RBAC v1beta1 support is enabled in the apiserver so we can default to RBAC
k8sVersion, err := semver.Parse(cfg.KubernetesVersion[1:])
if k8sVersion.GT(allowAllMaxVersion) {
cfg.AuthorizationMode = "RBAC"
}
fmt.Println("[init] Using Authorization mode:", cfg.AuthorizationMode)
// Warn about the limitations with the current cloudprovider solution.
if cfg.CloudProvider != "" {
fmt.Println("[init] WARNING: For cloudprovider integrations to work --cloud-provider must be set for all kubelets in the cluster.")
fmt.Println("\t(/etc/systemd/system/kubelet.service.d/10-kubeadm.conf should be edited for this purpose)")
}
// Validate token if any, otherwise generate
if cfg.Discovery.Token != nil {
if cfg.Discovery.Token.ID != "" && cfg.Discovery.Token.Secret != "" {
fmt.Printf("[init] A token has been provided, validating [%s]\n", kubeadmutil.BearerToken(cfg.Discovery.Token))
if valid, err := kubeadmutil.ValidateToken(cfg.Discovery.Token); valid == false {
return err
}
} else {
fmt.Println("[init] A token has not been provided, generating one")
if err := kubeadmutil.GenerateToken(cfg.Discovery.Token); err != nil {
return err
}
}
// If there aren't any addresses specified, default to the first advertised address which can be user-provided or the default network interface's IP address
if len(cfg.Discovery.Token.Addresses) == 0 {
cfg.Discovery.Token.Addresses = []string{cfg.API.AdvertiseAddresses[0] + ":" + strconv.Itoa(kubeadmapiext.DefaultDiscoveryBindPort)}
}
}
return nil
}
开发者ID:kubernetes,项目名称:kubernetes,代码行数:59,代码来源:defaults.go
示例17: Parse
func Parse(value string) Version {
semver, err := semver.Parse(value)
if err != nil {
return Version{Alias: value}
}
return Version{SemVer: semver}
}
开发者ID:40a,项目名称:dvm-1,代码行数:8,代码来源:dockerversion.go
示例18: isNewerVersion
func (cfg *Config) isNewerVersion(newer string) bool {
nv, err := semver.Parse(newer)
if err != nil {
log.Errorf("Bad version string on update: %v", err)
return false
}
return nv.GT(cfg.version)
}
开发者ID:ComeOn-Wuhan,项目名称:lantern,代码行数:8,代码来源:autoupdate.go
示例19: UnmarshalYAML
// UnmarshalYAML is a overridden implementation of YAML parsing the component.yaml
// This method is similar to the one found here: http://choly.ca/post/go-json-marshalling/
// This is necessary because we want to have backwards compatibility with parsing the old types of version 2.0
// (type =float).
// To compensate for that, we have to hand roll our own UnmarshalYAML that can decide what to do for parsing
// the older version of type float and converting it into semver. In addition, we will use this logic to parse strings
// into semver.
func (b *Base) UnmarshalYAML(unmarshal func(v interface{}) error) error {
// When we call "unmarshal" callback on an object, it will call that object's "UnmarshalYAML" if defined.
// Since we are currently in the implementation of Component's "UnmarshalYAML", when finally we call
// unmarshal again, if it's on type Component, we would end up in a recursive infinite loop.
// To prevent this, we create a separate type, called Alias.
type Alias Base
// Create an anonymous struct with an interface{} type for the schema_version that we want to parse
aux := &struct {
SchemaVersion interface{} `yaml:"schema_version" json:"schema_version"`
Alias `yaml:",inline"`
}{
Alias: (Alias)(*b),
}
// Call unmarshal on the new Alias type. Don't return the error yet because we want to gather more information
// if we can below.
err := unmarshal(&aux)
// Create a placeholder variable for the converted semver.
var ver semver.Version
// Create a placeholder variable for the error.
var versionErr error
// Store the version value for conciseness.
value := aux.SchemaVersion
// Try to cast the value from interface{} to certain types.
switch v := value.(type) {
// For float types, which are the old types, we need to upcast it to semver if it's an older version.
case float32, float64:
switch v {
// Schema Version started being documented with "2.0".
// We should be able to parse it for backwards compatibility.
// All future versioning should be in semver format already.
case 2.0:
ver = semver.MustParse("2.0.0")
// If not the older version, it needs to be in semver format, send an error.
default:
return BaseComponentParseError{fmt.Sprintf("Version %v is not in semver format", v)}
}
// The interface type will default to string if not numeric which is what all semver types will be initially.
case string:
ver, versionErr = semver.Parse(v)
if versionErr != nil {
return BaseComponentParseError{constants.ErrMissingVersion}
}
// In the case, it's just missing completely.
default:
return BaseComponentParseError{constants.ErrMissingVersion}
}
// Copy everything from the Alias back to the original component.
*b = (Base)(aux.Alias)
// Get the version
b.SchemaVersion = ver
return err
}
开发者ID:opencontrol,项目名称:compliance-masonry,代码行数:65,代码来源:component.go
示例20: getAPIServerCommand
func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
command := append(getComponentBaseCommand(apiServer),
"--insecure-bind-address=127.0.0.1",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
"--service-cluster-ip-range="+cfg.Networking.ServiceSubnet,
"--service-account-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver-key.pem",
"--client-ca-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca.pem",
"--tls-cert-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver.pem",
"--tls-private-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver-key.pem",
"--token-auth-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/tokens.csv",
fmt.Sprintf("--secure-port=%d", cfg.API.BindPort),
"--allow-privileged",
)
// Use first address we are given
if len(cfg.API.AdvertiseAddresses) > 0 {
command = append(command, fmt.Sprintf("--advertise-address=%s", cfg.API.AdvertiseAddresses[0]))
}
if len(cfg.KubernetesVersion) != 0 {
// If the k8s version is v1.5-something, this argument is set and makes `kubectl logs` and `kubectl exec`
// work on bare-metal where hostnames aren't usually resolvable
// Omit the "v" in the beginning, otherwise semver will fail
k8sVersion, err := semver.Parse(cfg.KubernetesVersion[1:])
if err == nil && k8sVersion.GTE(preferredAddressMinimumVersion) {
command = append(command, "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname")
}
}
// Check if the user decided to use an external etcd cluster
if len(cfg.Etcd.Endpoints) > 0 {
command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(cfg.Etcd.Endpoints, ",")))
} else {
command = append(command, "--etcd-servers=http://127.0.0.1:2379")
}
// Is etcd secured?
if cfg.Etcd.CAFile != "" {
command = append(command, fmt.Sprintf("--etcd-cafile=%s", cfg.Etcd.CAFile))
}
if cfg.Etcd.CertFile != "" && cfg.Etcd.KeyFile != "" {
etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", cfg.Etcd.CertFile)
etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", cfg.Etcd.KeyFile)
command = append(command, etcdClientFileArg, etcdKeyFileArg)
}
if cfg.CloudProvider != "" {
command = append(command, "--cloud-provider="+cfg.CloudProvider)
// Only append the --cloud-config option if there's a such file
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
command = append(command, "--cloud-config="+DefaultCloudConfigPath)
}
}
return command
}
开发者ID:abutcher,项目名称:kubernetes,代码行数:57,代码来源:manifests.go
注:本文中的github.com/blang/semver.Parse函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论