Skip to content

Commit

Permalink
Merge pull request #6 from phukon/next
Browse files Browse the repository at this point in the history
Release v4.0.0
  • Loading branch information
phukon authored Jan 14, 2025
2 parents f72b8a5 + 377cc34 commit c6da44c
Show file tree
Hide file tree
Showing 13 changed files with 395 additions and 370 deletions.
55 changes: 38 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,53 @@

Simplify PGP key setup and signing commits on Linux and Windows.

## 📦 Usage
## 📦 Installation

```bash
# Using npx (recommended)
npx gitkeykit
```
or
```bash

# Or install globally
npm install -g gitkeykit
```

## Features
## 🚀 Usage

### Basic Setup
```bash
# Start the interactive setup
gitkeykit

- **Effortless PGP Key Management**: Create or import PGP keys with ease to secure your Git commits.
- **Cross-Platform Compatibility**: Works seamlessly on both Linux and Windows machines, ensuring a consistent experience across environments.
- **Git and GPG Configuration**: Automatically configure Git and GPG settings for seamless integration with your workflow.
- **Secure Passphrase Entry**: Enhance security with pinentry-mode loopback, ensuring passphrases are entered securely.
- **Fast and Efficient Operation**: Enjoy a lightning-fast CLI tool that gets the job done quickly and efficiently.
# Import existing PGP key
gitkeykit import my_key.txt

# Reset configurations
gitkeykit --reset

# Show version number
gitkeykit --version

# Display help information and available commands
gitkeykit --help
```

### Command Options
- `--reset` Reset Git and GPG configurations
- `--help` Show help information
- `--version` Show version number
- `--import <key_path.txt>` Import and configure PGP key from file

## ✨ Features

#### Options:
`--reset` Reset Git and GPG configurations
- **Interactive Setup**: Guided process for creating or importing PGP keys
- **Cross-Platform**: Works seamlessly on both Linux and Windows
- **Secure Configuration**:
- Automatic Git signing setup
- GPG agent configuration
- Secure passphrase handling
- **Error Handling**: Clear error messages and recovery options
- **Backup & Reset**: Automatic backup of existing configurations with reset capability

#### Commands:
`import <key_path.txt>` Import and set configuration with the provided PGP key

Examples:
`gitkeykit import my_key.txt` Import and set configuration with 'my_key.txt'
`gitkeykit --reset` Reset all configurations`
## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
96 changes: 48 additions & 48 deletions bin/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
#!/usr/bin/env node
import arg from "arg";
import chalk from "chalk";
import { fileURLToPath } from 'url';
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import { readFileSync } from "fs";
import boxen from "boxen";
import { start } from "../src/commands/start";
import { reset } from "../src/commands/reset";
import { importKey } from "../src/commands/import";
import { GitKeyKitError, GitKeyKitCodes } from "../src/gitkeykitCodes";
import createLogger from "../src/utils/logger";
import boxen from 'boxen';
import { GitKeyKitCodes } from "../src/gitkeykitCodes";
import { dirname, join } from "path";
import { readFileSync } from "fs";

process.on("SIGINT", () => process.exit(GitKeyKitCodes.SUCCESS));
process.on("SIGTERM", () => process.exit(GitKeyKitCodes.SUCCESS));
const logger = createLogger("bin");

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const packageJson = JSON.parse(
readFileSync(join(__dirname, '../package.json'), 'utf8')
);
const packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf8"));
const { version } = packageJson;

const logger = createLogger("bin");

function usage() {
console.log("\n");
console.log(chalk.blueBright(boxen('GitKeyKit - Simplify PGP key🔑 setup and signing commits on Linux and Windows machines.', {padding: 1, borderStyle: 'round'})));
console.log(chalk.blueBright(boxen("GitKeyKit - Simplify PGP key🔑 setup and signing commits on Linux and Windows machines.", { padding: 1, borderStyle: "round" })));
console.log(chalk.whiteBright("Usage: gitkeykit\n"));
console.log(chalk.whiteBright("Options:"));
console.log(chalk.blueBright("--reset\t\t\tReset Git and GPG configurations"));
Expand All @@ -43,85 +38,90 @@ function usage() {
console.log("\n");
}

async function handleImport(keyPath: string): Promise<number> {
async function handleImport(keyPath: string): Promise<void> {
try {
await importKey(keyPath);
logger.log(`Imported key from ${keyPath}`);
await start();
return GitKeyKitCodes.SUCCESS;
} catch (error) {
console.error(`Error importing key from ${keyPath}:`, error);
return GitKeyKitCodes.ERR_KEY_IMPORT;
if (error instanceof GitKeyKitError) {
throw error;
}
throw new GitKeyKitError(`Failed to import key from ${keyPath}`, GitKeyKitCodes.KEY_IMPORT_ERROR, error);
}
}

async function handleReset(): Promise<number> {
async function handleReset(): Promise<void> {
try {
reset();
return GitKeyKitCodes.SUCCESS;
} catch (error: any) {
logger.warning((error as Error).message);
console.log();
usage();
return GitKeyKitCodes.ERR_GIT_CONFIG_RESET;
await reset();
} catch (error) {
if (error instanceof GitKeyKitError) {
throw error;
}
throw new GitKeyKitError("Failed to reset configurations", GitKeyKitCodes.GIT_CONFIG_RESET_ERROR, error);
}
}

async function main(): Promise<number> {
async function main(): Promise<void> {
try {
const args = arg({
"--reset": Boolean,
"--help": Boolean,
"--import": String,
"--version": Boolean
"--version": Boolean,
});

logger.debug("Received args", args);

if (Object.keys(args).length === 1) {
await start();
return GitKeyKitCodes.SUCCESS;
return;
}

if (args["--reset"]) {
return handleReset();
await handleReset();
return;
}

if (args["--help"]) {
usage();
return GitKeyKitCodes.SUCCESS;
return;
}

if (args["--import"]) {
const keyPath = args["--import"];
return handleImport(keyPath);
await handleImport(keyPath);
return;
}

if (args["--version"]) {
console.log(`v${version}`);
return GitKeyKitCodes.SUCCESS;
return;
}

usage();
return GitKeyKitCodes.ERR_INVALID_ARGS;
} catch (error: any) {
if (error?.code === 'ARG_UNKNOWN_OPTION') {
} catch (error) {
if (error instanceof arg.ArgError && error?.code === "ARG_UNKNOWN_OPTION") {
logger.error(`Invalid argument: ${error.message}`);
console.log('------');
console.log("------");
usage();
return GitKeyKitCodes.ERR_INVALID_ARGS;
process.exit(1);
}

if (error instanceof GitKeyKitError) {
logger.error(`Error: ${error.message} (${error.code})`);
if (error.details) {
logger.debug("Error details:", error.details);
}
process.exit(1);
}

// Handle any other unexpected errors
logger.error('An unexpected error occurred:', error);
return GitKeyKitCodes.ERR_INVALID_ARGS;

logger.error("An unexpected error occurred:", error);
process.exit(1);
}
}

// Execute and handle exit codes
main()
.then(exitCode => process.exit(exitCode))
.catch(error => {
console.error('Unexpected error:', error);
process.exit(1);
});
main().catch((error) => {
logger.error("Fatal error:", error);
process.exit(1);
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gitkeykit",
"version": "3.0.0",
"version": "4.0.0-next.1",
"description": "Setup pgp keys and sign commits with ease on Linux and Windows machines.",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
Expand Down
44 changes: 38 additions & 6 deletions src/commands/import.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,42 @@
import { readFileSync } from "fs";
import { execSync } from "child_process";
import { GitKeyKitCodes, GitKeyKitError } from "../gitkeykitCodes";
import createLogger from "../utils/logger";

export function importKey(key: string): boolean {
const logger = createLogger("commands:import");

/**
* Imports a GPG key from a file
* @param keyPath Path to the key file
* @throws {GitKeyKitError} If key import fails
*/
export async function importKey(keyPath: string): Promise<void> {
try {
execSync(`gpg --import ${key}`, { stdio: "inherit" });
return true; // Indicate success
} catch (error: any) {
throw new Error(`Error importing key: ${(error as Error).message}`);
let keyContent: string;
try {
keyContent = readFileSync(keyPath, "utf-8");
} catch (error) {
throw new GitKeyKitError(`Failed to read key file: ${keyPath}`, GitKeyKitCodes.KEY_IMPORT_ERROR, error);
}

if (!keyContent.includes("-----BEGIN PGP PRIVATE KEY BLOCK-----")) {
throw new GitKeyKitError("Invalid key file format: Missing PGP private key block", GitKeyKitCodes.KEY_IMPORT_ERROR);
}

try {
execSync("gpg --import", {
input: keyContent,
stdio: ["pipe", "inherit", "inherit"],
});

logger.green("GPG key imported successfully");
} catch (error) {
throw new GitKeyKitError("Failed to import GPG key", GitKeyKitCodes.KEY_IMPORT_ERROR, error);
}
} catch (error) {
if (error instanceof GitKeyKitError) {
throw error;
}
throw new GitKeyKitError("Unexpected error during key import", GitKeyKitCodes.KEY_IMPORT_ERROR, error);
}
}
}
Loading

0 comments on commit c6da44c

Please sign in to comment.