worktree-tool
Version:
A command-line tool for managing Git worktrees with integrated tmux/shell session management
89 lines • 2.91 kB
JavaScript
import { promises as fs } from "fs";
import * as path from "path";
import { sanitize } from "./sanitize.js";
/**
* Detect the project name from the current directory
* Tries package.json first, then falls back to directory name
* @param dir The directory to check (defaults to current directory)
* @returns The detected project name
*/
export async function detectProjectName(dir = process.cwd()) {
// First try to find package.json
const packageJsonPath = await findPackageJson(dir);
if (packageJsonPath) {
try {
const content = await fs.readFile(packageJsonPath, "utf-8");
const packageData = JSON.parse(content);
if (packageData.name && typeof packageData.name === "string") {
return sanitize(packageData.name, "PROJECT_NAME");
}
}
catch {
// Ignore errors reading/parsing package.json
// We'll fall back to directory name
}
}
// Fall back to directory name
const dirName = path.basename(dir);
return sanitize(dirName, "PROJECT_NAME");
}
/**
* Find package.json in the given directory or its parents
* @param dir The directory to start searching from
* @returns The path to package.json or null if not found
*/
export async function findPackageJson(dir) {
let currentDir = path.resolve(dir);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
while (true) {
const packageJsonPath = path.join(currentDir, "package.json");
try {
await fs.access(packageJsonPath);
return packageJsonPath;
}
catch {
// File doesn't exist, continue searching
}
const parentDir = path.dirname(currentDir);
if (parentDir === currentDir) {
// We've reached the root
break;
}
currentDir = parentDir;
}
return null;
}
/**
* Check if a name is valid for git branches
* @param name The name to check
* @returns True if valid, false otherwise
*/
export function isValidGitBranchName(name) {
// Git branch name rules:
// - Cannot start with '.' or end with '.'
// - Cannot contain '..'
// - Cannot contain ASCII control characters
// - Cannot contain ' ', '~', '^', ':', '?', '*', '[', '\\'
// - Cannot end with '.lock'
// - Cannot be '@'
if (!name || name === "@") {
return false;
}
if (name.startsWith(".") || name.endsWith(".")) {
return false;
}
if (name.includes("..")) {
return false;
}
if (name.endsWith(".lock")) {
return false;
}
// Check for invalid characters
// eslint-disable-next-line no-control-regex, no-useless-escape
const invalidChars = /[\x00-\x1F\x7F ~^:?*\[\\]/;
if (invalidChars.test(name)) {
return false;
}
return true;
}
//# sourceMappingURL=project.js.map