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:
@@ -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)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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[]> {
|
||||
|
||||
@@ -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!)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user