Add support for untracked files.

Untracked file glob patterns are stored in the servermeta.json. See the README for detailed information.
This commit is contained in:
Daniel Scalzi
2020-09-12 22:46:50 -04:00
parent 1a19df0e93
commit 24b0923903
14 changed files with 153 additions and 43 deletions

View File

@@ -3,7 +3,7 @@ import { Server, Module } from 'helios-distribution-types'
import { dirname, join, resolve as resolvePath } from 'path'
import { resolve as resolveUrl } from 'url'
import { VersionSegmentedRegistry } from '../../util/VersionSegmentedRegistry'
import { ServerMeta, getDefaultServerMeta, ServerMetaOptions } from '../../model/nebula/servermeta'
import { ServerMeta, getDefaultServerMeta, ServerMetaOptions, UntrackedFilesOption } from '../../model/nebula/servermeta'
import { BaseModelStructure } from './BaseModel.struct'
import { MiscFileStructure } from './module/File.struct'
import { LiteModStructure } from './module/LiteMod.struct'
@@ -60,14 +60,15 @@ export class ServerStructure extends BaseModelStructure<Server> {
options.forgeVersion,
absoluteServerRoot,
relativeServerRoot,
this.baseUrl
this.baseUrl,
[]
)
await fms.init()
serverMetaOpts.forgeVersion = options.forgeVersion
}
if (options.liteloaderVersion != null) {
const lms = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
const lms = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion, [])
await lms.init()
serverMetaOpts.liteloaderVersion = options.liteloaderVersion
}
@@ -75,10 +76,10 @@ export class ServerStructure extends BaseModelStructure<Server> {
const serverMeta: ServerMeta = getDefaultServerMeta(id, minecraftVersion.toString(), serverMetaOpts)
await writeFile(resolvePath(absoluteServerRoot, this.SERVER_META_FILE), JSON.stringify(serverMeta, null, 2))
const libS = new LibraryStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
const libS = new LibraryStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion, [])
await libS.init()
const mfs = new MiscFileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
const mfs = new MiscFileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion, [])
await mfs.init()
}
@@ -117,6 +118,7 @@ export class ServerStructure extends BaseModelStructure<Server> {
// Read server meta
const serverMeta: ServerMeta = JSON.parse(await readFile(resolvePath(absoluteServerRoot, this.SERVER_META_FILE), 'utf-8'))
const minecraftVersion = new MinecraftVersion(match[2])
const untrackedFiles: UntrackedFilesOption[] = serverMeta.untrackedFiles || []
const modules: Module[] = []
@@ -138,7 +140,8 @@ export class ServerStructure extends BaseModelStructure<Server> {
serverMeta.forge.version,
absoluteServerRoot,
relativeServerRoot,
this.baseUrl
this.baseUrl,
untrackedFiles
)
const forgeModModules = await forgeModStruct.getSpecModel()
@@ -147,16 +150,16 @@ export class ServerStructure extends BaseModelStructure<Server> {
if(serverMeta.liteloader) {
const liteModStruct = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
const liteModStruct = new LiteModStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion, untrackedFiles)
const liteModModules = await liteModStruct.getSpecModel()
modules.push(...liteModModules)
}
const libraryStruct = new LibraryStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
const libraryStruct = new LibraryStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion, untrackedFiles)
const libraryModules = await libraryStruct.getSpecModel()
modules.push(...libraryModules)
const fileStruct = new MiscFileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion)
const fileStruct = new MiscFileStructure(absoluteServerRoot, relativeServerRoot, this.baseUrl, minecraftVersion, untrackedFiles)
const fileModules = await fileStruct.getSpecModel()
modules.push(...fileModules)

View File

@@ -6,6 +6,7 @@ import { ModuleStructure } from './Module.struct'
import { readdir, stat } from 'fs-extra'
import { join, resolve, sep } from 'path'
import { MinecraftVersion } from '../../../util/MinecraftVersion'
import { UntrackedFilesOption } from '../../../model/nebula/servermeta'
export class MiscFileStructure extends ModuleStructure {
@@ -13,9 +14,10 @@ export class MiscFileStructure extends ModuleStructure {
absoluteRoot: string,
relativeRoot: string,
baseUrl: string,
minecraftVersion: MinecraftVersion
minecraftVersion: MinecraftVersion,
untrackedFiles: UntrackedFilesOption[]
) {
super(absoluteRoot, relativeRoot, 'files', baseUrl, minecraftVersion, Type.File)
super(absoluteRoot, relativeRoot, 'files', baseUrl, minecraftVersion, Type.File, untrackedFiles)
}
public getLoggerName(): string {

View File

@@ -7,6 +7,7 @@ import { MinecraftVersion } from '../../../util/MinecraftVersion'
import { ToggleableModuleStructure } from './ToggleableModule.struct'
import { LibraryType } from '../../../model/claritas/ClaritasLibraryType'
import { ClaritasException } from './Module.struct'
import { UntrackedFilesOption } from '../../../model/nebula/servermeta'
export abstract class BaseForgeModStructure extends ToggleableModuleStructure implements VersionSegmented {
@@ -16,9 +17,10 @@ export abstract class BaseForgeModStructure extends ToggleableModuleStructure im
absoluteRoot: string,
relativeRoot: string,
baseUrl: string,
minecraftVersion: MinecraftVersion
minecraftVersion: MinecraftVersion,
untrackedFiles: UntrackedFilesOption[]
) {
super(absoluteRoot, relativeRoot, 'forgemods', baseUrl, minecraftVersion, Type.ForgeMod)
super(absoluteRoot, relativeRoot, 'forgemods', baseUrl, minecraftVersion, Type.ForgeMod, untrackedFiles)
}
public async getSpecModel(): Promise<Module[]> {

View File

@@ -4,6 +4,7 @@ import { Stats } from 'fs-extra'
import { join } from 'path'
import { resolve } from 'url'
import { MinecraftVersion } from '../../../util/MinecraftVersion'
import { UntrackedFilesOption } from '../../../model/nebula/servermeta'
export class LibraryStructure extends ModuleStructure {
@@ -11,9 +12,10 @@ export class LibraryStructure extends ModuleStructure {
absoluteRoot: string,
relativeRoot: string,
baseUrl: string,
minecraftVersion: MinecraftVersion
minecraftVersion: MinecraftVersion,
untrackedFiles: UntrackedFilesOption[]
) {
super(absoluteRoot, relativeRoot, 'libraries', baseUrl, minecraftVersion, Type.Library, (name: string) => {
super(absoluteRoot, relativeRoot, 'libraries', baseUrl, minecraftVersion, Type.Library, untrackedFiles, (name: string) => {
return name.toLowerCase().endsWith(TypeMetadata[this.type].defaultExtension!)
})
}

View File

@@ -9,6 +9,7 @@ import { ToggleableModuleStructure } from './ToggleableModule.struct'
import { MinecraftVersion } from '../../../util/MinecraftVersion'
import { LibraryType } from '../../../model/claritas/ClaritasLibraryType'
import { MetadataUtil } from '../../../util/MetadataUtil'
import { UntrackedFilesOption } from '../../../model/nebula/servermeta'
export class LiteModStructure extends ToggleableModuleStructure {
@@ -18,9 +19,10 @@ export class LiteModStructure extends ToggleableModuleStructure {
absoluteRoot: string,
relativeRoot: string,
baseUrl: string,
minecraftVersion: MinecraftVersion
minecraftVersion: MinecraftVersion,
untrackedFiles: UntrackedFilesOption[]
) {
super(absoluteRoot, relativeRoot, 'litemods', baseUrl, minecraftVersion, Type.LiteMod)
super(absoluteRoot, relativeRoot, 'litemods', baseUrl, minecraftVersion, Type.LiteMod, untrackedFiles)
}
public getLoggerName(): string {

View File

@@ -1,12 +1,14 @@
import minimatch from 'minimatch'
import { createHash } from 'crypto'
import { lstat, pathExists, readdir, readFile, Stats } from 'fs-extra'
import { Module, Type, TypeMetadata } from 'helios-distribution-types'
import { Artifact, Module, Type, TypeMetadata } from 'helios-distribution-types'
import { resolve } from 'path'
import { BaseModelStructure } from '../BaseModel.struct'
import { LibraryType } from '../../../model/claritas/ClaritasLibraryType'
import { ClaritasResult, ClaritasModuleMetadata } from '../../../model/claritas/ClaritasResult'
import { ClaritasWrapper } from '../../../util/java/ClaritasWrapper'
import { MinecraftVersion } from '../../../util/MinecraftVersion'
import { UntrackedFilesOption } from '../../../model/nebula/servermeta'
export interface ModuleCandidate {
file: string
@@ -24,6 +26,7 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
private readonly crudeRegex = /(.+?)-(.+).[jJ][aA][rR]/
protected readonly DEFAULT_VERSION = '0.0.0'
protected untrackedFilePatterns: string[] // List of glob patterns.
protected claritasResult!: ClaritasResult
constructor(
@@ -33,9 +36,11 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
baseUrl: string,
protected minecraftVersion: MinecraftVersion,
protected type: Type,
untrackedFiles: UntrackedFilesOption[],
protected filter?: ((name: string, path: string, stats: Stats) => boolean)
) {
super(absoluteRoot, relativeRoot, structRoot, baseUrl)
this.untrackedFilePatterns = this.determineUntrackedFiles(structRoot, untrackedFiles)
}
public async getSpecModel(): Promise<Module[]> {
@@ -87,16 +92,26 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
protected async abstract getModulePath(name: string, path: string, stats: Stats): Promise<string | null>
protected async parseModule(file: string, filePath: string, stats: Stats): Promise<Module> {
const buf = await readFile(filePath)
const artifact: Artifact = {
size: stats.size,
url: await this.getModuleUrl(file, filePath, stats)
}
const relativeToContainer = filePath.substr(this.containerDirectory.length+1)
const untrackedByPattern = this.isFileUntracked(relativeToContainer)
if(!untrackedByPattern) {
const buf = await readFile(filePath)
artifact.MD5 = createHash('md5').update(buf).digest('hex')
} else {
this.logger.debug(`File ${relativeToContainer} is untracked. Matching pattern: ${untrackedByPattern}`)
}
const mdl: Module = {
id: await this.getModuleId(file, filePath),
name: await this.getModuleName(file, filePath),
type: this.type,
artifact: {
size: stats.size,
MD5: createHash('md5').update(buf).digest('hex'),
url: await this.getModuleUrl(file, filePath, stats)
}
artifact
}
const pth = await this.getModulePath(file, filePath, stats)
if (pth) {
@@ -182,4 +197,18 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
}
protected determineUntrackedFiles(targetStructRoot: string, untrackedFileOptions?: UntrackedFilesOption[]): string[] {
if(untrackedFileOptions) {
return untrackedFileOptions
.filter(x => x.appliesTo.includes(targetStructRoot))
.reduce((acc, cur) => acc.concat(cur.patterns), [] as string[])
}
return []
}
// Will return the matching pattern, undefined if no match.
protected isFileUntracked(pathRelativeToContainer: string): string | undefined {
return this.untrackedFilePatterns.find(pattern => minimatch(pathRelativeToContainer, pattern))
}
}

View File

@@ -3,6 +3,7 @@ import { Type, Module } from 'helios-distribution-types'
import { Stats, mkdirs } from 'fs-extra'
import { resolve } from 'path'
import { MinecraftVersion } from '../../../util/MinecraftVersion'
import { UntrackedFilesOption } from '../../../model/nebula/servermeta'
export enum ToggleableNamespace {
@@ -27,9 +28,10 @@ export abstract class ToggleableModuleStructure extends ModuleStructure {
baseUrl: string,
minecraftVersion: MinecraftVersion,
type: Type,
untrackedFiles: UntrackedFilesOption[],
filter?: ((name: string, path: string, stats: Stats) => boolean)
) {
super(absoluteRoot, relativeRoot, structRoot, baseUrl, minecraftVersion, type, filter)
super(absoluteRoot, relativeRoot, structRoot, baseUrl, minecraftVersion, type, untrackedFiles, filter)
}
public async init(): Promise<void> {

View File

@@ -5,6 +5,7 @@ import { VersionUtil } from '../../../../util/versionutil'
import { ModsToml } from '../../../../model/forge/modstoml'
import { BaseForgeModStructure } from '../ForgeMod.struct'
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
import { UntrackedFilesOption } from '../../../../model/nebula/servermeta'
export class ForgeModStructure113 extends BaseForgeModStructure {
@@ -21,9 +22,10 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
absoluteRoot: string,
relativeRoot: string,
baseUrl: string,
minecraftVersion: MinecraftVersion
minecraftVersion: MinecraftVersion,
untrackedFiles: UntrackedFilesOption[]
) {
super(absoluteRoot, relativeRoot, baseUrl, minecraftVersion)
super(absoluteRoot, relativeRoot, baseUrl, minecraftVersion, untrackedFiles)
}
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {

View File

@@ -6,6 +6,7 @@ import { McModInfoList } from '../../../../model/forge/mcmodinfolist'
import { BaseForgeModStructure } from '../ForgeMod.struct'
import { MinecraftVersion } from '../../../../util/MinecraftVersion'
import { ForgeModType_1_7 } from '../../../../model/claritas/ClaritasResult'
import { UntrackedFilesOption } from '../../../../model/nebula/servermeta'
export class ForgeModStructure17 extends BaseForgeModStructure {
@@ -20,9 +21,10 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
absoluteRoot: string,
relativeRoot: string,
baseUrl: string,
minecraftVersion: MinecraftVersion
minecraftVersion: MinecraftVersion,
untrackedFiles: UntrackedFilesOption[]
) {
super(absoluteRoot, relativeRoot, baseUrl, minecraftVersion)
super(absoluteRoot, relativeRoot, baseUrl, minecraftVersion, untrackedFiles)
}
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {