diff --git a/docker-compose.yml b/docker-compose.yml index 79d51e73..47f73603 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -119,9 +119,9 @@ services: security_opt: - seccomp=unconfined # for gdb volumes: - - .:/chalk + - $PWD:$PWD - /var/run/docker.sock:/var/run/docker.sock - working_dir: /chalk/tests + working_dir: $PWD/tests networks: - chalk - imds diff --git a/src/confload.nim b/src/confload.nim index e6865726..c6d62c23 100644 --- a/src/confload.nim +++ b/src/confload.nim @@ -90,7 +90,14 @@ proc findOptionalConf(state: ConfigState): Option[(string, FileStream)] = path = unpack[seq[string]](state.attrLookup("config_path").get()) filename = unpack[string](state.attrLookup("config_filename").get()) for dir in path: - let fname = resolvePath(dir.joinPath(filename)) + var fname = "" + try: + fname = resolvePath(dir.joinPath(filename)) + except: + # resolvePath can fail in some cases such as ~ might not resolve + # if uid does not have home folder + trace(filename & ": Cannot resolve configuration file path.") + continue trace("Looking for config file at: " & fname) if fname.fileExists(): info(fname & ": Found config file") @@ -107,8 +114,17 @@ proc loadLocalStructs*(state: ConfigState) = chalkConfig = state.attrs.loadChalkConfig() if chalkConfig.color.isSome(): setShowColor(chalkConfig.color.get()) setLogLevel(chalkConfig.logLevel) - for i in 0 ..< len(chalkConfig.configPath): - chalkConfig.configPath[i] = chalkConfig.configPath[i].resolvePath() + var configPath: seq[string] = @[] + for path in chalkConfig.configPath: + try: + configPath.add(path.resolvePath()) + except: + # resolvePath can fail in some cases such as ~ might not resolve + # if uid does not have home folder + # no log as this function is called multiple times + # and any logs are very verbose + continue + chalkConfig.configPath = configPath var c4errLevel = if chalkConfig.con4mPinpoint: c4vShowLoc else: c4vBasic if chalkConfig.chalkDebug: diff --git a/src/selfextract.nim b/src/selfextract.nim index 4ac6d88e..c2ff4d12 100644 --- a/src/selfextract.nim +++ b/src/selfextract.nim @@ -28,9 +28,17 @@ proc getSelfExtraction*(): Option[ChalkObj] = # have a codec for this type of executable, avoid dupe errors. once: var - myPath = resolvePath(getMyAppPath()) + myPath = getMyAppPath() cmd = getCommandName() + try: + myPath = myPath.resolvePath() + except: + # should not happen as getMyAppPath should return absolute path + # however resolvePath can fail in some cases such as when + # path contains ~ but uid does not have home directory + discard + setCommandName("extract") # This can stay here, but won't show if the log level is set in the @@ -61,16 +69,7 @@ proc getSelfExtraction*(): Option[ChalkObj] = # of lettus to enjoy ;D # If not, we immediately exit with hopefully useful error message # :fingerscrossed: - var canOpen = false - try: - let stream = newFileStream(myPath) - if stream != nil: - canOpen = true - stream.close() - except: - dumpExOnDebug() - error(getCurrentExceptionMsg()) - if not canOpen: + if not canOpenFile(myPath): cantLoad("Chalk is unable to read self-config. " & "Ensure chalk has both read and execute permissions. " & "To add permissions run: 'chmod +rx " & myPath & "'\n") diff --git a/src/sinks.nim b/src/sinks.nim index 414df30c..118a1742 100644 --- a/src/sinks.nim +++ b/src/sinks.nim @@ -73,7 +73,8 @@ template formatIo(cfg: SinkConfig, t: Topic, err: string, msg: string): string = case cfg.mySink.name of "rotating_log", "file": - line &= cfg.params["actual_file"] & ": " + if "actual_file" in cfg.params: + line &= cfg.params["actual_file"] & ": " else: discard diff --git a/src/util.nim b/src/util.nim index 2908eb9d..fabb849b 100644 --- a/src/util.nim +++ b/src/util.nim @@ -106,6 +106,24 @@ proc reportTmpFileExitState*(files, dirs, errs: seq[string]) = 1000000000) & " seconds" +proc canOpenFile*(path: string, mode: FileMode = FileMode.fmRead): bool = + var canOpen = false + try: + let stream = openFileStream(path, mode = mode) + if stream != nil: + canOpen = true + stream.close() + except: + dumpExOnDebug() + error(getCurrentExceptionMsg()) + finally: + if mode != FileMode.fmRead: + try: + discard tryRemoveFile(path) + except: + discard + return canOpen + proc setupManagedTemp*() = let customTmpDirOpt = chalkConfig.getDefaultTmpDir() @@ -119,14 +137,19 @@ proc setupManagedTemp*() = discard existsOrCreateDir(getEnv("TMPDIR")) if chalkConfig.getChalkDebug(): - info("Debug is on; temp files / dirs will be moved, not deleted.") - setManagedTmpCopyLocation(resolvePath("chalk-tmp")) + let + tmpPath = resolvePath("chalk-tmp") + tmpCheck = resolvePath(".chalk-tmp-check") + if canOpenFile(tmpCheck, mode = FileMode.fmWrite): + info("Debug is on; temp files / dirs will be moved to " & tmpPath & ", not deleted.") + setManagedTmpCopyLocation(tmpPath) + else: + warn("Debug is on however chalk is unable to move temp files to " & tmpPath) setManagedTmpExitCallback(reportTmpFileExitState) setDefaultTmpFilePrefix(tmpFilePrefix) setDefaultTmpFileSuffix(tmpFileSuffix) - when hostOs == "macosx": const staticScriptLoc = "autocomplete/mac.bash" else: @@ -230,10 +253,15 @@ proc validateMetadata*(obj: ChalkObj): ValidateResult {.importc.} proc autocompleteFileCheck*() = if isatty(0) == 0 or chalkConfig.getInstallCompletionScript() == false: return - let - dst = resolvePath(autoCompleteLoc) - alreadyExists = fileExists(dst) + var dst = "" + try: + dst = resolvePath(autoCompleteLoc) + except: + # resolvePath can fail on ~ when uid doesnt have home dir + return + + let alreadyExists = fileExists(dst) if alreadyExists: var invalidMark = true diff --git a/tests/test_docker.py b/tests/test_docker.py index 7ac19698..b31a1c83 100644 --- a/tests/test_docker.py +++ b/tests/test_docker.py @@ -678,3 +678,14 @@ def test_extract(chalk: Chalk, random_hex: str): virtual=False, chalk_action="extract", ) + + +def test_docker_diff_user(chalk_default: Chalk): + assert Docker.run( + "alpine", + entrypoint="/chalk", + params=["version"], + volumes={chalk_default.binary: "/chalk"}, + cwd=chalk_default.binary.parent, + user="1000:1000", + ) diff --git a/tests/utils/docker.py b/tests/utils/docker.py index 2b196638..a56edd65 100644 --- a/tests/utils/docker.py +++ b/tests/utils/docker.py @@ -151,6 +151,9 @@ def run( tty: bool = True, check: bool = True, attach: bool = True, + user: Optional[str] = None, + volumes: Optional[dict[Path, Path | str]] = None, + cwd: Optional[Path] = None, ): cmd = ["docker", "create"] if name: @@ -161,6 +164,12 @@ def run( cmd += ["--entrypoint", entrypoint] if tty: cmd += ["-t"] + if user: + cmd += ["-u", user] + for host, container in (volumes or {}).items(): + cmd += ["-v", f"{host}:{container}"] + if cwd: + cmd += ["-w", str(cwd)] cmd += [image] cmd += params or [] container_id = run(cmd).text