Skip to content

Commit

Permalink
fix: various issues with path handling on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
edvald committed Jul 17, 2019
1 parent a5f172c commit ea001d4
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 20 deletions.
6 changes: 6 additions & 0 deletions garden-service/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion garden-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"moment": "^2.24.0",
"node-emoji": "^1.10.0",
"node-forge": "^0.8.2",
"normalize-path": "^3.0.0",
"normalize-url": "^4.3.0",
"p-queue": "^5.0.0",
"p-retry": "^4.1.0",
Expand Down Expand Up @@ -142,6 +143,7 @@
"@types/node": "^12.0.1",
"@types/node-emoji": "^1.8.1",
"@types/node-forge": "^0.8.2",
"@types/normalize-path": "^3.0.0",
"@types/path-is-inside": "^1.0.0",
"@types/pluralize": "0.0.29",
"@types/prettyjson": "0.0.29",
Expand Down Expand Up @@ -212,4 +214,4 @@
},
"snyk": true,
"gitHead": "b0647221a4d2ff06952bae58000b104215aed922"
}
}
12 changes: 4 additions & 8 deletions garden-service/src/bin/add-version-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { Logger } from "../logger/logger"
import { LogLevel } from "../logger/log-node"
import { resolve, relative } from "path"
import * as Bluebird from "bluebird"
import { writeFile } from "fs-extra"
import { STATIC_DIR } from "../constants"
import { STATIC_DIR, GARDEN_VERSIONFILE_NAME } from "../constants"
import { writeTreeVersionFile } from "../vcs/vcs"

// make sure logger is initialized
try {
Expand All @@ -30,18 +30,14 @@ async function addVersionFiles() {

return Bluebird.map(moduleConfigs, async (config) => {
const path = config.path
const versionFilePath = resolve(path, ".garden-version")
const versionFilePath = resolve(path, GARDEN_VERSIONFILE_NAME)

const vcsHandler = new GitHandler(garden.gardenDirPath)
const treeVersion = await vcsHandler.getTreeVersion(path, config.include || null)

treeVersion.files = treeVersion.files
.map(f => relative(path, f))
.filter(f => f !== ".garden-version")

console.log(`${config.name} -> ${relative(STATIC_DIR, versionFilePath)}`)

return writeFile(versionFilePath, JSON.stringify(treeVersion, null, 4) + "\n")
return writeTreeVersionFile(path, treeVersion)
})
}

Expand Down
6 changes: 5 additions & 1 deletion garden-service/src/build-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import { map as bluebirdMap } from "bluebird"
import normalize = require("normalize-path")
import {
isAbsolute,
join,
Expand Down Expand Up @@ -38,7 +39,8 @@ export class BuildDir {

async syncFromSrc(module: Module, log: LogEntry) {
const files = module.version.files
.map(f => isAbsolute(f) ? relative(module.path, f) : f)
// Normalize to relative POSIX-style paths
.map(f => normalize(isAbsolute(f) ? relative(module.path, f) : f))

await this.sync({
module,
Expand Down Expand Up @@ -150,7 +152,9 @@ export class BuildDir {

if (files !== undefined) {
syncOpts.push("--files-from=-")
files = files.sort()
input = files.join("\n")
log.silly(`File list: ${JSON.stringify(files)}`)
}

await execa("rsync", [...syncOpts, sourcePath, destinationPath], { input })
Expand Down
2 changes: 1 addition & 1 deletion garden-service/src/plugins/kubernetes/container/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ const remoteBuild: BuildHandler = async (params) => {
const buildRoot = resolve(module.buildPath, "..")
// The '/./' trick is used to automatically create the correct target directory with rsync:
// https://stackoverflow.com/questions/1636889/rsync-how-can-i-configure-it-to-create-target-directory-on-server
let src = normalizeLocalRsyncPath(`${buildRoot}/./${module.name}/`)
let src = normalizeLocalRsyncPath(`${buildRoot}`) + `/./${module.name}/`

const destination = `rsync://localhost:${syncFwd.localPort}/volume/${ctx.workingCopyId}/`

Expand Down
31 changes: 23 additions & 8 deletions garden-service/src/vcs/vcs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

import * as Joi from "@hapi/joi"
import * as Bluebird from "bluebird"
import normalize = require("normalize-path")
import { mapValues, keyBy, sortBy, omit } from "lodash"
import { createHash } from "crypto"
import { validate, joiArray, joi } from "../config/common"
import { join } from "path"
import { GARDEN_VERSIONFILE_NAME } from "../constants"
import { join, relative, isAbsolute } from "path"
import { GARDEN_VERSIONFILE_NAME as GARDEN_TREEVERSION_FILENAME } from "../constants"
import { pathExists, readFile, writeFile } from "fs-extra"
import { ConfigurationError } from "../exceptions"
import { ExternalSourceType, getRemoteSourcesDirname, getRemoteSourceRelPath } from "../util/ext-source-util"
Expand Down Expand Up @@ -93,7 +94,7 @@ export abstract class VcsHandler {

async resolveTreeVersion(path: string, include: string[] | null): Promise<TreeVersion> {
// the version file is used internally to specify versions outside of source control
const versionFilePath = join(path, GARDEN_VERSIONFILE_NAME)
const versionFilePath = join(path, GARDEN_TREEVERSION_FILENAME)
const fileVersion = await readTreeVersionFile(versionFilePath)
return fileVersion || this.getTreeVersion(path, include)
}
Expand Down Expand Up @@ -176,16 +177,30 @@ export async function readTreeVersionFile(path: string): Promise<TreeVersion | n
return readVersionFile(path, treeVersionSchema)
}

export async function writeTreeVersionFile(path: string, version: TreeVersion) {
await writeFile(path, JSON.stringify(version))
}

export async function readModuleVersionFile(path: string): Promise<ModuleVersion | null> {
return readVersionFile(path, moduleVersionSchema)
}

/**
* Writes a normalized TreeVersion file to the specified directory
*
* @param dir The directory to write the file to
* @param version The TreeVersion for the directory
*/
export async function writeTreeVersionFile(dir: string, version: TreeVersion) {
const processed = {
...version,
files: version.files
// Always write relative paths, normalized to POSIX style
.map(f => normalize(isAbsolute(f) ? relative(dir, f) : f))
.filter(f => f !== GARDEN_TREEVERSION_FILENAME),
}
const path = join(dir, GARDEN_TREEVERSION_FILENAME)
await writeFile(path, JSON.stringify(processed, null, 4) + "\n")
}

export async function writeModuleVersionFile(path: string, version: ModuleVersion) {
await writeFile(path, JSON.stringify(version))
await writeFile(path, JSON.stringify(version, null, 4) + "\n")
}

/**
Expand Down
68 changes: 67 additions & 1 deletion garden-service/test/unit/src/vcs/vcs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
TreeVersions,
TreeVersion,
getVersionString,
writeTreeVersionFile,
readTreeVersionFile,
} from "../../../../src/vcs/vcs"
import { projectRootA, makeTestGardenA, makeTestGarden, getDataDir } from "../../../helpers"
import { expect } from "chai"
Expand All @@ -11,8 +13,11 @@ import { Garden } from "../../../../src/garden"
import { ModuleConfigContext } from "../../../../src/config/config-context"
import { ModuleConfig } from "../../../../src/config/module"
import { GitHandler } from "../../../../src/vcs/git"
import { resolve } from "path"
import { resolve, join } from "path"
import * as td from "testdouble"
import * as tmp from "tmp-promise"
import { realpath } from "fs-extra"
import { GARDEN_VERSIONFILE_NAME } from "../../../../src/constants"

class TestVcsHandler extends VcsHandler {
name = "test"
Expand Down Expand Up @@ -258,3 +263,64 @@ describe("VcsHandler", () => {
})
})
})

describe("writeTreeVersionFile", () => {
let tmpDir: tmp.DirectoryResult
let tmpPath: string

beforeEach(async () => {
tmpDir = await tmp.dir({ unsafeCleanup: true })
tmpPath = await realpath(tmpDir.path)
})

afterEach(async () => {
await tmpDir.cleanup()
})

describe("writeVersionFile", () => {
it("should write relative paths for files", async () => {
await writeTreeVersionFile(tmpPath, {
contentHash: "foo",
files: [
join(tmpPath, "some", "file"),
],
})
expect(await readTreeVersionFile(join(tmpPath, GARDEN_VERSIONFILE_NAME))).to.eql({
contentHash: "foo",
files: [
"some/file",
],
})
})

it("should handle relative paths in input", async () => {
await writeTreeVersionFile(tmpPath, {
contentHash: "foo",
files: [
"some/file",
],
})
expect(await readTreeVersionFile(join(tmpPath, GARDEN_VERSIONFILE_NAME))).to.eql({
contentHash: "foo",
files: [
"some/file",
],
})
})

it("should normalize Windows-style paths to POSIX-style", async () => {
await writeTreeVersionFile(tmpPath, {
contentHash: "foo",
files: [
`some\\file`,
],
})
expect(await readTreeVersionFile(join(tmpPath, GARDEN_VERSIONFILE_NAME))).to.eql({
contentHash: "foo",
files: [
"some/file",
],
})
})
})
})

0 comments on commit ea001d4

Please sign in to comment.