Best Rod code snippet using launcher.Append
python.go
Source:python.go
1// Copyright 2017 Google Inc. All rights reserved.2//3// Licensed under the Apache License, Version 2.0 (the "License");4// you may not use this file except in compliance with the License.5// You may obtain a copy of the License at6//7// http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// distributed under the License is distributed on an "AS IS" BASIS,11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12// See the License for the specific language governing permissions and13// limitations under the License.14package python15// This file contains the "Base" module type for building Python program.16import (17 "fmt"18 "path/filepath"19 "regexp"20 "sort"21 "strings"22 "github.com/google/blueprint"23 "github.com/google/blueprint/proptools"24 "android/soong/android"25)26func init() {27 android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {28 ctx.BottomUp("version_split", versionSplitMutator()).Parallel()29 })30}31// the version properties that apply to python libraries and binaries.32type VersionProperties struct {33 // true, if the module is required to be built with this version.34 Enabled *bool `android:"arch_variant"`35 // non-empty list of .py files under this strict Python version.36 // srcs may reference the outputs of other modules that produce source files like genrule37 // or filegroup using the syntax ":module".38 Srcs []string `android:"path,arch_variant"`39 // list of source files that should not be used to build the Python module.40 // This is most useful in the arch/multilib variants to remove non-common files41 Exclude_srcs []string `android:"path,arch_variant"`42 // list of the Python libraries under this Python version.43 Libs []string `android:"arch_variant"`44 // true, if the binary is required to be built with embedded launcher.45 // TODO(nanzhang): Remove this flag when embedded Python3 is supported later.46 Embedded_launcher *bool `android:"arch_variant"`47}48// properties that apply to python libraries and binaries.49type BaseProperties struct {50 // the package path prefix within the output artifact at which to place the source/data51 // files of the current module.52 // eg. Pkg_path = "a/b/c"; Other packages can reference this module by using53 // (from a.b.c import ...) statement.54 // if left unspecified, all the source/data files path is unchanged within zip file.55 Pkg_path *string `android:"arch_variant"`56 // true, if the Python module is used internally, eg, Python std libs.57 Is_internal *bool `android:"arch_variant"`58 // list of source (.py) files compatible both with Python2 and Python3 used to compile the59 // Python module.60 // srcs may reference the outputs of other modules that produce source files like genrule61 // or filegroup using the syntax ":module".62 // Srcs has to be non-empty.63 Srcs []string `android:"path,arch_variant"`64 // list of source files that should not be used to build the C/C++ module.65 // This is most useful in the arch/multilib variants to remove non-common files66 Exclude_srcs []string `android:"path,arch_variant"`67 // list of files or filegroup modules that provide data that should be installed alongside68 // the test. the file extension can be arbitrary except for (.py).69 Data []string `android:"path,arch_variant"`70 // list of the Python libraries compatible both with Python2 and Python3.71 Libs []string `android:"arch_variant"`72 Version struct {73 // all the "srcs" or Python dependencies that are to be used only for Python2.74 Py2 VersionProperties `android:"arch_variant"`75 // all the "srcs" or Python dependencies that are to be used only for Python3.76 Py3 VersionProperties `android:"arch_variant"`77 } `android:"arch_variant"`78 // the actual version each module uses after variations created.79 // this property name is hidden from users' perspectives, and soong will populate it during80 // runtime.81 Actual_version string `blueprint:"mutated"`82}83type pathMapping struct {84 dest string85 src android.Path86}87type Module struct {88 android.ModuleBase89 android.DefaultableModuleBase90 properties BaseProperties91 protoProperties android.ProtoProperties92 // initialize before calling Init93 hod android.HostOrDeviceSupported94 multilib android.Multilib95 // the bootstrapper is used to bootstrap .par executable.96 // bootstrapper might be nil (Python library module).97 bootstrapper bootstrapper98 // the installer might be nil.99 installer installer100 // the Python files of current module after expanding source dependencies.101 // pathMapping: <dest: runfile_path, src: source_path>102 srcsPathMappings []pathMapping103 // the data files of current module after expanding source dependencies.104 // pathMapping: <dest: runfile_path, src: source_path>105 dataPathMappings []pathMapping106 // the zip filepath for zipping current module source/data files.107 srcsZip android.Path108 // dependency modules' zip filepath for zipping current module source/data files.109 depsSrcsZips android.Paths110 // (.intermediate) module output path as installation source.111 installSource android.OptionalPath112 subAndroidMkOnce map[subAndroidMkProvider]bool113}114func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {115 return &Module{116 hod: hod,117 multilib: multilib,118 }119}120type bootstrapper interface {121 bootstrapperProps() []interface{}122 bootstrap(ctx android.ModuleContext, ActualVersion string, embeddedLauncher bool,123 srcsPathMappings []pathMapping, srcsZip android.Path,124 depsSrcsZips android.Paths) android.OptionalPath125 autorun() bool126}127type installer interface {128 install(ctx android.ModuleContext, path android.Path)129 setAndroidMkSharedLibs(sharedLibs []string)130}131type PythonDependency interface {132 GetSrcsPathMappings() []pathMapping133 GetDataPathMappings() []pathMapping134 GetSrcsZip() android.Path135}136func (p *Module) GetSrcsPathMappings() []pathMapping {137 return p.srcsPathMappings138}139func (p *Module) GetDataPathMappings() []pathMapping {140 return p.dataPathMappings141}142func (p *Module) GetSrcsZip() android.Path {143 return p.srcsZip144}145var _ PythonDependency = (*Module)(nil)146var _ android.AndroidMkDataProvider = (*Module)(nil)147func (p *Module) Init() android.Module {148 p.AddProperties(&p.properties, &p.protoProperties)149 if p.bootstrapper != nil {150 p.AddProperties(p.bootstrapper.bootstrapperProps()...)151 }152 android.InitAndroidArchModule(p, p.hod, p.multilib)153 android.InitDefaultableModule(p)154 return p155}156type dependencyTag struct {157 blueprint.BaseDependencyTag158 name string159}160var (161 pythonLibTag = dependencyTag{name: "pythonLib"}162 launcherTag = dependencyTag{name: "launcher"}163 launcherSharedLibTag = dependencyTag{name: "launcherSharedLib"}164 pyIdentifierRegexp = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)165 pyExt = ".py"166 protoExt = ".proto"167 pyVersion2 = "PY2"168 pyVersion3 = "PY3"169 initFileName = "__init__.py"170 mainFileName = "__main__.py"171 entryPointFile = "entry_point.txt"172 parFileExt = ".zip"173 internal = "internal"174)175// create version variants for modules.176func versionSplitMutator() func(android.BottomUpMutatorContext) {177 return func(mctx android.BottomUpMutatorContext) {178 if base, ok := mctx.Module().(*Module); ok {179 versionNames := []string{}180 if base.properties.Version.Py2.Enabled != nil &&181 *(base.properties.Version.Py2.Enabled) == true {182 versionNames = append(versionNames, pyVersion2)183 }184 if !(base.properties.Version.Py3.Enabled != nil &&185 *(base.properties.Version.Py3.Enabled) == false) {186 versionNames = append(versionNames, pyVersion3)187 }188 modules := mctx.CreateVariations(versionNames...)189 for i, v := range versionNames {190 // set the actual version for Python module.191 modules[i].(*Module).properties.Actual_version = v192 }193 }194 }195}196func (p *Module) HostToolPath() android.OptionalPath {197 if p.installer == nil {198 // python_library is just meta module, and doesn't have any installer.199 return android.OptionalPath{}200 }201 return android.OptionalPathForPath(p.installer.(*binaryDecorator).path)202}203func (p *Module) isEmbeddedLauncherEnabled(actual_version string) bool {204 switch actual_version {205 case pyVersion2:206 return Bool(p.properties.Version.Py2.Embedded_launcher)207 case pyVersion3:208 return Bool(p.properties.Version.Py3.Embedded_launcher)209 }210 return false211}212func hasSrcExt(srcs []string, ext string) bool {213 for _, src := range srcs {214 if filepath.Ext(src) == ext {215 return true216 }217 }218 return false219}220func (p *Module) hasSrcExt(ctx android.BottomUpMutatorContext, ext string) bool {221 if hasSrcExt(p.properties.Srcs, protoExt) {222 return true223 }224 switch p.properties.Actual_version {225 case pyVersion2:226 return hasSrcExt(p.properties.Version.Py2.Srcs, protoExt)227 case pyVersion3:228 return hasSrcExt(p.properties.Version.Py3.Srcs, protoExt)229 default:230 panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",231 p.properties.Actual_version, ctx.ModuleName()))232 }233}234func (p *Module) DepsMutator(ctx android.BottomUpMutatorContext) {235 android.ProtoDeps(ctx, &p.protoProperties)236 if p.hasSrcExt(ctx, protoExt) && p.Name() != "libprotobuf-python" {237 ctx.AddVariationDependencies(nil, pythonLibTag, "libprotobuf-python")238 }239 switch p.properties.Actual_version {240 case pyVersion2:241 ctx.AddVariationDependencies(nil, pythonLibTag,242 uniqueLibs(ctx, p.properties.Libs, "version.py2.libs",243 p.properties.Version.Py2.Libs)...)244 if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled(pyVersion2) {245 ctx.AddVariationDependencies(nil, pythonLibTag, "py2-stdlib")246 launcherModule := "py2-launcher"247 if p.bootstrapper.autorun() {248 launcherModule = "py2-launcher-autorun"249 }250 ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherTag, launcherModule)251 // Add py2-launcher shared lib dependencies. Ideally, these should be252 // derived from the `shared_libs` property of "py2-launcher". However, we253 // cannot read the property at this stage and it will be too late to add254 // dependencies later.255 ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag, "libsqlite")256 if ctx.Target().Os.Bionic() {257 ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag,258 "libc", "libdl", "libm")259 }260 }261 case pyVersion3:262 ctx.AddVariationDependencies(nil, pythonLibTag,263 uniqueLibs(ctx, p.properties.Libs, "version.py3.libs",264 p.properties.Version.Py3.Libs)...)265 if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled(pyVersion3) {266 ctx.AddVariationDependencies(nil, pythonLibTag, "py3-stdlib")267 launcherModule := "py3-launcher"268 if p.bootstrapper.autorun() {269 launcherModule = "py3-launcher-autorun"270 }271 ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherTag, launcherModule)272 // Add py3-launcher shared lib dependencies. Ideally, these should be273 // derived from the `shared_libs` property of "py3-launcher". However, we274 // cannot read the property at this stage and it will be too late to add275 // dependencies later.276 ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag, "libsqlite")277 if ctx.Device() {278 ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag,279 "liblog")280 }281 if ctx.Target().Os.Bionic() {282 ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag,283 "libc", "libdl", "libm")284 }285 }286 default:287 panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",288 p.properties.Actual_version, ctx.ModuleName()))289 }290}291// check "libs" duplicates from current module dependencies.292func uniqueLibs(ctx android.BottomUpMutatorContext,293 commonLibs []string, versionProp string, versionLibs []string) []string {294 set := make(map[string]string)295 ret := []string{}296 // deps from "libs" property.297 for _, l := range commonLibs {298 if _, found := set[l]; found {299 ctx.PropertyErrorf("libs", "%q has duplicates within libs.", l)300 } else {301 set[l] = "libs"302 ret = append(ret, l)303 }304 }305 // deps from "version.pyX.libs" property.306 for _, l := range versionLibs {307 if _, found := set[l]; found {308 ctx.PropertyErrorf(versionProp, "%q has duplicates within %q.", set[l])309 } else {310 set[l] = versionProp311 ret = append(ret, l)312 }313 }314 return ret315}316func (p *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {317 p.GeneratePythonBuildActions(ctx)318 // Only Python binaries and test has non-empty bootstrapper.319 if p.bootstrapper != nil {320 p.walkTransitiveDeps(ctx)321 embeddedLauncher := false322 if p.properties.Actual_version == pyVersion2 {323 embeddedLauncher = p.isEmbeddedLauncherEnabled(pyVersion2)324 } else {325 embeddedLauncher = p.isEmbeddedLauncherEnabled(pyVersion3)326 }327 p.installSource = p.bootstrapper.bootstrap(ctx, p.properties.Actual_version,328 embeddedLauncher, p.srcsPathMappings, p.srcsZip, p.depsSrcsZips)329 }330 if p.installer != nil {331 var sharedLibs []string332 ctx.VisitDirectDeps(func(dep android.Module) {333 if ctx.OtherModuleDependencyTag(dep) == launcherSharedLibTag {334 sharedLibs = append(sharedLibs, ctx.OtherModuleName(dep))335 }336 })337 p.installer.setAndroidMkSharedLibs(sharedLibs)338 if p.installSource.Valid() {339 p.installer.install(ctx, p.installSource.Path())340 }341 }342}343func (p *Module) GeneratePythonBuildActions(ctx android.ModuleContext) {344 // expand python files from "srcs" property.345 srcs := p.properties.Srcs346 exclude_srcs := p.properties.Exclude_srcs347 switch p.properties.Actual_version {348 case pyVersion2:349 srcs = append(srcs, p.properties.Version.Py2.Srcs...)350 exclude_srcs = append(exclude_srcs, p.properties.Version.Py2.Exclude_srcs...)351 case pyVersion3:352 srcs = append(srcs, p.properties.Version.Py3.Srcs...)353 exclude_srcs = append(exclude_srcs, p.properties.Version.Py3.Exclude_srcs...)354 default:355 panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",356 p.properties.Actual_version, ctx.ModuleName()))357 }358 expandedSrcs := android.PathsForModuleSrcExcludes(ctx, srcs, exclude_srcs)359 requiresSrcs := true360 if p.bootstrapper != nil && !p.bootstrapper.autorun() {361 requiresSrcs = false362 }363 if len(expandedSrcs) == 0 && requiresSrcs {364 ctx.ModuleErrorf("doesn't have any source files!")365 }366 // expand data files from "data" property.367 expandedData := android.PathsForModuleSrc(ctx, p.properties.Data)368 // sanitize pkg_path.369 pkgPath := String(p.properties.Pkg_path)370 if pkgPath != "" {371 pkgPath = filepath.Clean(String(p.properties.Pkg_path))372 if pkgPath == ".." || strings.HasPrefix(pkgPath, "../") ||373 strings.HasPrefix(pkgPath, "/") {374 ctx.PropertyErrorf("pkg_path",375 "%q must be a relative path contained in par file.",376 String(p.properties.Pkg_path))377 return378 }379 if p.properties.Is_internal != nil && *p.properties.Is_internal {380 pkgPath = filepath.Join(internal, pkgPath)381 }382 } else {383 if p.properties.Is_internal != nil && *p.properties.Is_internal {384 pkgPath = internal385 }386 }387 p.genModulePathMappings(ctx, pkgPath, expandedSrcs, expandedData)388 p.srcsZip = p.createSrcsZip(ctx, pkgPath)389}390// generate current module unique pathMappings: <dest: runfiles_path, src: source_path>391// for python/data files.392func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkgPath string,393 expandedSrcs, expandedData android.Paths) {394 // fetch <runfiles_path, source_path> pairs from "src" and "data" properties to395 // check current module duplicates.396 destToPySrcs := make(map[string]string)397 destToPyData := make(map[string]string)398 for _, s := range expandedSrcs {399 if s.Ext() != pyExt && s.Ext() != protoExt {400 ctx.PropertyErrorf("srcs", "found non (.py|.proto) file: %q!", s.String())401 continue402 }403 runfilesPath := filepath.Join(pkgPath, s.Rel())404 identifiers := strings.Split(strings.TrimSuffix(runfilesPath,405 filepath.Ext(runfilesPath)), "/")406 for _, token := range identifiers {407 if !pyIdentifierRegexp.MatchString(token) {408 ctx.PropertyErrorf("srcs", "the path %q contains invalid token %q.",409 runfilesPath, token)410 }411 }412 if fillInMap(ctx, destToPySrcs, runfilesPath, s.String(), p.Name(), p.Name()) {413 p.srcsPathMappings = append(p.srcsPathMappings,414 pathMapping{dest: runfilesPath, src: s})415 }416 }417 for _, d := range expandedData {418 if d.Ext() == pyExt || d.Ext() == protoExt {419 ctx.PropertyErrorf("data", "found (.py|.proto) file: %q!", d.String())420 continue421 }422 runfilesPath := filepath.Join(pkgPath, d.Rel())423 if fillInMap(ctx, destToPyData, runfilesPath, d.String(), p.Name(), p.Name()) {424 p.dataPathMappings = append(p.dataPathMappings,425 pathMapping{dest: runfilesPath, src: d})426 }427 }428}429// register build actions to zip current module's sources.430func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) android.Path {431 relativeRootMap := make(map[string]android.Paths)432 pathMappings := append(p.srcsPathMappings, p.dataPathMappings...)433 var protoSrcs android.Paths434 // "srcs" or "data" properties may have filegroup so it might happen that435 // the relative root for each source path is different.436 for _, path := range pathMappings {437 if path.src.Ext() == protoExt {438 protoSrcs = append(protoSrcs, path.src)439 } else {440 var relativeRoot string441 relativeRoot = strings.TrimSuffix(path.src.String(), path.src.Rel())442 if v, found := relativeRootMap[relativeRoot]; found {443 relativeRootMap[relativeRoot] = append(v, path.src)444 } else {445 relativeRootMap[relativeRoot] = android.Paths{path.src}446 }447 }448 }449 var zips android.Paths450 if len(protoSrcs) > 0 {451 protoFlags := android.GetProtoFlags(ctx, &p.protoProperties)452 protoFlags.OutTypeFlag = "--python_out"453 for _, srcFile := range protoSrcs {454 zip := genProto(ctx, srcFile, protoFlags, pkgPath)455 zips = append(zips, zip)456 }457 }458 if len(relativeRootMap) > 0 {459 var keys []string460 // in order to keep stable order of soong_zip params, we sort the keys here.461 for k := range relativeRootMap {462 keys = append(keys, k)463 }464 sort.Strings(keys)465 parArgs := []string{}466 if pkgPath != "" {467 parArgs = append(parArgs, `-P `+pkgPath)468 }469 implicits := android.Paths{}470 for _, k := range keys {471 parArgs = append(parArgs, `-C `+k)472 for _, path := range relativeRootMap[k] {473 parArgs = append(parArgs, `-f `+path.String())474 implicits = append(implicits, path)475 }476 }477 origSrcsZip := android.PathForModuleOut(ctx, ctx.ModuleName()+".py.srcszip")478 ctx.Build(pctx, android.BuildParams{479 Rule: zip,480 Description: "python library archive",481 Output: origSrcsZip,482 Implicits: implicits,483 Args: map[string]string{484 "args": strings.Join(parArgs, " "),485 },486 })487 zips = append(zips, origSrcsZip)488 }489 if len(zips) == 1 {490 return zips[0]491 } else {492 combinedSrcsZip := android.PathForModuleOut(ctx, ctx.ModuleName()+".srcszip")493 ctx.Build(pctx, android.BuildParams{494 Rule: combineZip,495 Description: "combine python library archive",496 Output: combinedSrcsZip,497 Inputs: zips,498 })499 return combinedSrcsZip500 }501}502func isPythonLibModule(module blueprint.Module) bool {503 if m, ok := module.(*Module); ok {504 // Python library has no bootstrapper or installer.505 if m.bootstrapper != nil || m.installer != nil {506 return false507 }508 return true509 }510 return false511}512// check Python source/data files duplicates for whole runfiles tree since Python binary/test513// need collect and zip all srcs of whole transitive dependencies to a final par file.514func (p *Module) walkTransitiveDeps(ctx android.ModuleContext) {515 // fetch <runfiles_path, source_path> pairs from "src" and "data" properties to516 // check duplicates.517 destToPySrcs := make(map[string]string)518 destToPyData := make(map[string]string)519 for _, path := range p.srcsPathMappings {520 destToPySrcs[path.dest] = path.src.String()521 }522 for _, path := range p.dataPathMappings {523 destToPyData[path.dest] = path.src.String()524 }525 seen := make(map[android.Module]bool)526 // visit all its dependencies in depth first.527 ctx.WalkDeps(func(child, parent android.Module) bool {528 if ctx.OtherModuleDependencyTag(child) != pythonLibTag {529 return false530 }531 if seen[child] {532 return false533 }534 seen[child] = true535 // Python modules only can depend on Python libraries.536 if !isPythonLibModule(child) {537 panic(fmt.Errorf(538 "the dependency %q of module %q is not Python library!",539 ctx.ModuleName(), ctx.OtherModuleName(child)))540 }541 if dep, ok := child.(PythonDependency); ok {542 srcs := dep.GetSrcsPathMappings()543 for _, path := range srcs {544 if !fillInMap(ctx, destToPySrcs,545 path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child)) {546 continue547 }548 }549 data := dep.GetDataPathMappings()550 for _, path := range data {551 fillInMap(ctx, destToPyData,552 path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child))553 }554 p.depsSrcsZips = append(p.depsSrcsZips, dep.GetSrcsZip())555 }556 return true557 })558}559func fillInMap(ctx android.ModuleContext, m map[string]string,560 key, value, curModule, otherModule string) bool {561 if oldValue, found := m[key]; found {562 ctx.ModuleErrorf("found two files to be placed at the same location within zip %q."+563 " First file: in module %s at path %q."+564 " Second file: in module %s at path %q.",565 key, curModule, oldValue, otherModule, value)566 return false567 } else {568 m[key] = value569 }570 return true571}572func (p *Module) InstallInData() bool {573 return true574}575var Bool = proptools.Bool576var BoolDefault = proptools.BoolDefault577var String = proptools.String...
shortman.go
Source:shortman.go
1package shortman2import (3 "errors"4 "os"5 "path"6 "strings"7 "github.com/stephen-fox/grundy/internal/results"8 "github.com/stephen-fox/grundy/internal/settings"9 "github.com/stephen-fox/grundy/internal/steamw"10)11type ShortcutManager interface {12 RefreshAll(steamDataInfo steamw.DataInfo) []results.Result13 Update(gamePaths []string, isDirs bool, steamDataInfo steamw.DataInfo) []results.Result14 Delete(gamePaths []string, isDirs bool, steamDataInfo steamw.DataInfo) []results.Result15}16type defaultShortcutManager struct {17 config Config18}19func (o *defaultShortcutManager) RefreshAll(steamDataInfo steamw.DataInfo) []results.Result {20 var deletedDirPaths []string21 var existingDirPaths []string22 for dirPath := range o.config.KnownGames.GameDirPathsToGameNames() {23 info, statErr := os.Stat(dirPath)24 if statErr != nil {25 deletedDirPaths = append(deletedDirPaths, dirPath)26 } else if info.IsDir() {27 existingDirPaths = append(existingDirPaths, dirPath)28 } else {29 deletedDirPaths = append(deletedDirPaths, dirPath)30 }31 }32 var r []results.Result33 r = append(r, o.Update(existingDirPaths, true, steamDataInfo)...)34 r = append(r, o.Delete(deletedDirPaths, true, steamDataInfo)...)35 return r36}37func (o *defaultShortcutManager) Update(gamePaths []string, isDirs bool, dataInfo steamw.DataInfo) []results.Result {38 var r []results.Result39 for _, gameDir := range gamePaths {40 if strings.HasPrefix(gameDir, o.config.IgnorePathPrefix) {41 continue42 }43 if !isDirs {44 gameDir = path.Dir(gameDir)45 }46 collectionName := path.Dir(gameDir)47 launcherName, hasGameCollection := o.config.App.HasGameCollection(collectionName)48 if !hasGameCollection {49 r = append(r, results.NewUpdateShortcutSkipped(gameDir,50 "game collection '" + collectionName + "' does not exist"))51 continue52 }53 launcher, hasLauncher := o.config.Launchers.Has(launcherName)54 if !hasLauncher {55 r = append(r, results.NewUpdateShortcutSkipped(gameDir,56 "the specified launcher does not exist in the launchers settings - '" +57 launcherName + "'"))58 continue59 }60 game := settings.NewGameSettings(gameDir)61 var err error62 if strings.HasSuffix(gameDir, settings.FileExtension) {63 game, err = settings.LoadGameSettings(gameDir, launcher)64 } else {65 exeFilePath, exeExists := game.ExeFullPath(launcher)66 if !exeExists {67 err = errors.New("the game's executable does not exist at '" + exeFilePath + "'")68 }69 }70 if err != nil {71 r = append(r, results.NewUpdateShortcutFailed(gameDir, err.Error()))72 continue73 }74 // TODO: Is this a good idea? Can we be certain that the shortcut75 // was not removed by someone/thing else besides us?76 added := o.config.KnownGames.AddUniqueGameOnly(game, gameDir)77 if !added {78 r = append(r, results.NewUpdateShortcutSkipped(gameDir, "the game already exists"))79 continue80 }81 var warnings []string82 icon := game.IconPath()83 if !icon.WasDynamicallySelected() && !icon.FileExists() {84 r = append(r, results.NewUpdateShortcutFailed(gameDir,85 "manual icon does not exist at - '" +86 icon.FilePath() + "'"))87 continue88 } else if icon.WasDynamicallySelected() && !icon.FileExists() {89 warnings = append(warnings, "no icon was provided")90 }91 gridImage := game.GridImagePath()92 if !gridImage.WasDynamicallySelected() && !gridImage.FileExists() {93 r = append(r, results.NewUpdateShortcutFailed(gameDir,94 "manual grid image does not exist at - '" +95 gridImage.FilePath() + "'"))96 continue97 } else if gridImage.WasDynamicallySelected() && !gridImage.FileExists() {98 warnings = append(warnings, "no grid image was provided")99 }100 config := steamw.NewShortcutConfig{101 Name: game.Name(),102 LaunchOptions: createLauncherArgs(game, launcher),103 ExePath: launcher.ExePath(),104 IconPath: icon.FilePath(),105 GridImagePath: gridImage.FilePath(),106 Tags: game.Categories(),107 Info: dataInfo,108 Warnings: warnings,109 }110 r = append(r, steamw.CreateOrUpdateShortcut(config)...)111 }112 return r113}114// TODO: Refactor this.115func createLauncherArgs(game settings.GameSettings, launcher settings.Launcher) []string {116 var options []string117 if game.ShouldOverrideLauncherArgs() {118 options = append(options, game.LauncherOverrideArgs())119 } else {120 if len(launcher.DefaultArgs()) > 0 {121 options = append(options, launcher.DefaultArgs())122 }123 if len(game.AdditionalLauncherArgs()) > 0 {124 options = append(options, game.AdditionalLauncherArgs())125 }126 }127 exePath, _ := game.ExeFullPath(launcher)128 options = append(options, "\"" + exePath + "\"")129 return options130}131func (o *defaultShortcutManager) Delete(gamePaths []string, isDirs bool, dataInfo steamw.DataInfo) []results.Result {132 var r []results.Result133 for _, p := range gamePaths {134 if strings.HasPrefix(p, o.config.IgnorePathPrefix) {135 continue136 }137 if !isDirs {138 p = path.Dir(p)139 }140 var launcherExePath string141 // Do not delete if there is an executable in the directory.142 launcherName, hasCollection := o.config.App.HasGameCollection(p)143 if hasCollection {144 launcher, hasLauncher := o.config.Launchers.Has(launcherName)145 if hasLauncher {146 launcherExePath = launcher.ExePath()147 game := settings.NewGameSettings(p)148 exePath, exeExists := game.ExeFullPath(launcher)149 if exeExists {150 r = append(r, results.NewDeleteShortcutSkipped(game.Name(),151 "a game executable still exists in its directory at '" + exePath + "'"))152 continue153 }154 }155 }156 gameName, ok := o.config.KnownGames.Disown(p)157 if ok {158 config := steamw.DeleteShortcutConfig{159 GameName: gameName,160 Info: dataInfo,161 SkipGridImageDelete: len(launcherExePath) == 0,162 LauncherExePath: launcherExePath,163 }164 r = append(r, steamw.DeleteShortcut(config)...)165 }166 }167 return r168}169type Config struct {170 App settings.AppSettings171 KnownGames settings.KnownGamesSettings172 Launchers settings.LaunchersSettings173 IgnorePathPrefix string174}175func NewShortcutManager(config Config) ShortcutManager {176 return &defaultShortcutManager{177 config: config,178 }179}...
flags.go
Source:flags.go
1// Package flags manages the launcher's flags. For any changes, you should check if they2// are consistent with locking.Restart().3package flags4import (5 "flag"6 "fmt"7 "regexp"8 "strconv"9)10type LauncherFlags struct {11 Uninstall bool12 Debug bool13 SkipSelfUpdate bool14 NoStreamPassing bool15 Roaming bool16 PrintBuildTime bool17 DeploymentConfig string18 AcceptInstall bool19 AcceptUninstall bool20 DismissGuiPrompts bool21 LogIndexCounter int22 LogInstanceCounter int23 nextLogIndex int24}25const (26 UninstallFlag = "uninstall"27 DebugFlag = "debug"28 SkipSelfUpdateFlag = "skipselfupdate"29 NoStreamPassingFlag = "nostreampassing"30 RoamingFlag = "roaming"31 PrintBuildTimeFlag = "build-time"32 DeploymentConfigFlag = "deployment-config"33 AcceptInstallFlag = "accept-install"34 AcceptUninstallFlag = "accept-uninstall"35 DismissGuiPromptsFlag = "dismiss-gui-prompts"36 LogIndexCounterFlag = "log-index"37 LogInstanceCounterFlag = "log-instance"38)39func Setup(args []string) (*LauncherFlags, error) {40 launcherFlags := LauncherFlags{nextLogIndex: -1}41 // MacOS might append program serial number which we have to ignore/remove from args42 ignoredArgsExp := regexp.MustCompile("-+psn.*")43 for i, arg := range args {44 if ignoredArgsExp.MatchString(arg) {45 args = append(args[:i], args[i+1:]...)46 break47 }48 }49 flagSet := flag.NewFlagSet(args[0], flag.ContinueOnError)50 flagSet.BoolVar(&launcherFlags.Uninstall, UninstallFlag, false, "Remove the launcher and its bundles from the local machine.")51 flagSet.BoolVar(&launcherFlags.Debug, DebugFlag, false, "Write verbose information to the log files.")52 flagSet.BoolVar(&launcherFlags.SkipSelfUpdate, SkipSelfUpdateFlag, false, "Skip any updates to this launcher.")53 flagSet.BoolVar(&launcherFlags.NoStreamPassing, NoStreamPassingFlag, false, "Do not relay standard streams to executed commands.")54 flagSet.BoolVar(&launcherFlags.Roaming, RoamingFlag, false, "Put all files which would go under %LOCALAPPDATA% on Windows to %APPDATA% instead.")55 flagSet.BoolVar(&launcherFlags.PrintBuildTime, PrintBuildTimeFlag, false, "Print the output of 'date -u \"+%Y-%m-%d %H:%M:%S UTC\"' from the time the binary "+56 "was built to standard out and exit immediately.")57 flagSet.StringVar(&launcherFlags.DeploymentConfig, DeploymentConfigFlag, "", "Override the embedded URL of the deployment-config.")58 flagSet.BoolVar(&launcherFlags.AcceptInstall, AcceptInstallFlag, false, fmt.Sprintf("Accept install prompt when it is dismissed. Use with -%s.", DismissGuiPromptsFlag))59 flagSet.BoolVar(&launcherFlags.AcceptUninstall, AcceptUninstallFlag, false, fmt.Sprintf("Accept uninstall prompt when it is dismissed. Use with -%s.", DismissGuiPromptsFlag))60 flagSet.BoolVar(&launcherFlags.DismissGuiPrompts, DismissGuiPromptsFlag, false, "Automatically dismiss GUI prompts.")61 flagSet.IntVar(&launcherFlags.LogIndexCounter, LogIndexCounterFlag, -1, "Number to increment when restarting.")62 flagSet.IntVar(&launcherFlags.LogInstanceCounter, LogInstanceCounterFlag, 0, "Number to increment when started by user.")63 setDeprecatedFlags(flagSet)64 err := flagSet.Parse(args[1:])65 if err != nil {66 return &launcherFlags, withSuggestions(err, flagSet, []string{DebugFlag, RoamingFlag, SkipSelfUpdateFlag, UninstallFlag})67 }68 if !launcherFlags.DismissGuiPrompts && launcherFlags.AcceptInstall {69 return &launcherFlags, fmt.Errorf("-%s was set when -%s was not", AcceptInstallFlag, DismissGuiPromptsFlag)70 }71 if !launcherFlags.DismissGuiPrompts && launcherFlags.AcceptUninstall {72 return &launcherFlags, fmt.Errorf("-%s was set when -%s was not", AcceptUninstallFlag, DismissGuiPromptsFlag)73 }74 return &launcherFlags, nil75}76func withSuggestions(err error, flagSet *flag.FlagSet, suggestFlags []string) error {77 if len(suggestFlags) == 0 {78 return err79 }80 suggestionText := ". Maybe you meant one of these:"81 for _, suggestFlag := range suggestFlags {82 if f := flagSet.Lookup(suggestFlag); f != nil {83 suggestionText += "\n" + "\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0-" + f.Name + ": " + f.Usage84 } else {85 suggestionText += "\n" + "\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0-" + f.Name86 }87 }88 return fmt.Errorf("%w%s", err, suggestionText)89}90// GetTransmittingFlags returns those flags which the launcher should hand to itself when restarting.91func (launcherFlags *LauncherFlags) GetTransmittingFlags() (transmittingFlags []string) {92 transmittingFlags = append(transmittingFlags, "-"+LogIndexCounterFlag, strconv.Itoa(launcherFlags.nextLogIndex))93 transmittingFlags = append(transmittingFlags, "-"+LogInstanceCounterFlag, strconv.Itoa(launcherFlags.LogInstanceCounter+1))94 if launcherFlags.Uninstall {95 transmittingFlags = append(transmittingFlags, "-"+UninstallFlag)96 }97 if launcherFlags.Debug {98 transmittingFlags = append(transmittingFlags, "-"+DebugFlag)99 }100 if launcherFlags.SkipSelfUpdate {101 transmittingFlags = append(transmittingFlags, "-"+SkipSelfUpdateFlag)102 }103 if launcherFlags.Roaming {104 transmittingFlags = append(transmittingFlags, "-"+RoamingFlag)105 }106 if launcherFlags.DeploymentConfig != "" {107 transmittingFlags = append(transmittingFlags, "-"+DeploymentConfigFlag, launcherFlags.DeploymentConfig)108 }109 if launcherFlags.AcceptInstall {110 transmittingFlags = append(transmittingFlags, "-"+AcceptInstallFlag)111 }112 if launcherFlags.AcceptUninstall {113 transmittingFlags = append(transmittingFlags, "-"+AcceptUninstallFlag)114 }115 if launcherFlags.DismissGuiPrompts {116 transmittingFlags = append(transmittingFlags, "-"+DismissGuiPromptsFlag)117 }118 if launcherFlags.NoStreamPassing {119 transmittingFlags = append(transmittingFlags, "-"+NoStreamPassingFlag)120 }121 return transmittingFlags122}123func (launcherFlags *LauncherFlags) SetNextLogIndex(index int) {124 launcherFlags.nextLogIndex = index125}126func setDeprecatedFlags(flagSet *flag.FlagSet) {127 flagSet.String("remove", "", "DEPRECATED: Name of binary to remove upon launch.")128}...
Append
Using AI Code Generation
1import "fmt"2func main() {3 launcher.Append(1)4 launcher.Append(2)5 launcher.Append(3)6 launcher.Append(4)7 launcher.Append(5)8 launcher.Append(6)9 launcher.Append(7)10 launcher.Append(8)11 launcher.Append(9)12 launcher.Append(10)13 launcher.Append(11)14 launcher.Append(12)15 launcher.Append(13)16 launcher.Append(14)17 launcher.Append(15)18 launcher.Append(16)19 launcher.Append(17)20 launcher.Append(18)21 launcher.Append(19)22 launcher.Append(20)23 launcher.Append(21)24 launcher.Append(22)25 launcher.Append(23)26 launcher.Append(24)27 launcher.Append(25)28 launcher.Append(26)29 launcher.Append(27)30 launcher.Append(28)31 launcher.Append(29)32 launcher.Append(30)33 launcher.Append(31)34 launcher.Append(32)35 launcher.Append(33)36 launcher.Append(34)37 launcher.Append(35)38 launcher.Append(36)39 launcher.Append(37)40 launcher.Append(38)41 launcher.Append(39)42 launcher.Append(40)43 launcher.Append(41)44 launcher.Append(42)45 launcher.Append(43)46 launcher.Append(44)47 launcher.Append(45)48 launcher.Append(46)49 launcher.Append(47)50 launcher.Append(48)51 launcher.Append(49)52 launcher.Append(50)53 launcher.Append(51)54 launcher.Append(52)55 launcher.Append(53)56 launcher.Append(54)57 launcher.Append(55)58 launcher.Append(56)59 launcher.Append(57)60 launcher.Append(58)61 launcher.Append(59)62 launcher.Append(60)63 launcher.Append(61)64 launcher.Append(62)65 launcher.Append(63)66 launcher.Append(64)67 launcher.Append(65)68 launcher.Append(66)69 launcher.Append(67)70 launcher.Append(68)71 launcher.Append(69)72 launcher.Append(70)73 launcher.Append(71)74 launcher.Append(72)75 launcher.Append(73)76 launcher.Append(74)77 launcher.Append(75)78 launcher.Append(76)79 launcher.Append(77)80 launcher.Append(78)81 launcher.Append(79)82 launcher.Append(80)
Append
Using AI Code Generation
1import (2func main() {3 l.Append(1)4 l.Append(2)5 fmt.Println(l)6}
Append
Using AI Code Generation
1import "github.com/lukechampine/advent/day2"2func main() {3 day2.Append()4}5import "github.com/lukechampine/advent/day3"6func main() {7 day3.Append()8}9import "github.com/lukechampine/advent/day4"10func main() {11 day4.Append()12}13import "github.com/lukechampine/advent/day5"14func main() {15 day5.Append()16}17import "github.com/lukechampine/advent/day6"18func main() {19 day6.Append()20}21import "github.com/lukechampine/advent/day7"22func main() {23 day7.Append()24}25import "github.com/lukechampine/advent/day8"26func main() {27 day8.Append()28}29import "github.com/lukechampine/advent/day9"30func main() {31 day9.Append()32}33import "github.com/lukechampine/advent/day10"34func main() {35 day10.Append()36}37import "github.com/lukechampine/advent/day11"38func main() {39 day11.Append()40}41import "github.com/lukechampine/advent/day12"42func main() {43 day12.Append()44}45import "github.com/lukechampine/ad
Append
Using AI Code Generation
1import (2func main() {3 l = launcher.NewLauncher()4 l.Append("firefox")5 l.Append("gedit")6 l.Append("gnome-terminal")7 l.Append("nautilus")8 l.Append("gimp")9 l.Append("libreoffice")10 l.Append("gparted")11 l.Append("thunderbird")12 l.Append("vlc")13 l.Append("eog")14 l.Append("evince")15 l.Append("pidgin")16 l.Append("chromium-browser")17 fmt.Println(l)
Append
Using AI Code Generation
1import "fmt"2type launcher struct {3}4func (l launcher) Append() {5 fmt.Println("Append method of launcher class")6}7func main() {8 l.Append()9}10import "fmt"11type launcher struct {12}13func (l launcher) Append() {14 fmt.Println("Append method of launcher class")15}16func main() {17 l.Append()18 fmt.Println(l)19}20{Hawk 120}21import "fmt"22type launcher struct {23}24func (l launcher) Append() {25 fmt.Println("Append method of launcher class")26}27func main() {28 l.Append()29 fmt.Println(l)30 l.Append()31}32{Hawk 120}33import "fmt"34type launcher struct {35}36func (l launcher) Append() {37 fmt.Println("Append method of launcher class")38}39func main() {40 l.Append()41 fmt.Println(l)42 l.Append()43 l1.Append()44}45{Hawk 120}
Append
Using AI Code Generation
1import (2func main() {3 launcher := new(Launcher)4 launcher.Append("A")5 launcher.Append("B")6 launcher.Append("C")7 fmt.Println(launcher)8}
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!