Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
5ba6c5370e | |||
c6e3a1caa3 | |||
a92275088b | |||
2b246502f5 | |||
81b2b225a3 |
17
changelog.md
17
changelog.md
@@ -1,12 +1,21 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-01-04 - 3.2.0 - feat(core)
|
||||
Enhanced error handling, type safety, and documentation
|
||||
|
||||
- Add comprehensive error handling with try/catch blocks and meaningful error messages
|
||||
- Improve type safety with proper IEnvDeps interface replacing 'any' types
|
||||
- Add complete JSDoc documentation for all classes and methods
|
||||
- Add return type annotations for better TypeScript support
|
||||
- Add ensureInitialized() validation method
|
||||
- Fix missing return statement in createRepoByClone() method
|
||||
- Remove deprecated @types/minimatch dependency
|
||||
- Complete readme rewrite with modern styling, accurate documentation, and proper API examples
|
||||
- Update license from LICENSE to license.md following project guidelines
|
||||
|
||||
## 2024-06-23 - 3.1.1 - fix(documentation)
|
||||
Remove outdated changelog entries
|
||||
|
||||
-
|
||||
|
||||
|
||||
|
||||
## 2024-06-23 - 3.1.0 - gitrepo
|
||||
Enhancements and fixes to GitRepo
|
||||
|
||||
|
31
package.json
31
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@push.rocks/smartgit",
|
||||
"version": "3.1.1",
|
||||
"version": "3.2.1",
|
||||
"description": "A smart wrapper for nodegit that simplifies Git operations in Node.js.",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
@@ -32,23 +32,21 @@
|
||||
},
|
||||
"homepage": "https://code.foss.global/push.rocks/smartgit",
|
||||
"dependencies": {
|
||||
"@push.rocks/smartenv": "^5.0.12",
|
||||
"@push.rocks/smartfile": "^11.0.20",
|
||||
"@push.rocks/smartpath": "^5.0.18",
|
||||
"@push.rocks/smartpromise": "^4.0.2",
|
||||
"@push.rocks/smartshell": "^3.0.5",
|
||||
"@push.rocks/smartenv": "^5.0.13",
|
||||
"@push.rocks/smartfile": "^11.2.5",
|
||||
"@push.rocks/smartpath": "^6.0.0",
|
||||
"@push.rocks/smartpromise": "^4.2.3",
|
||||
"@push.rocks/smartshell": "^3.2.3",
|
||||
"@push.rocks/smartstring": "^4.0.15",
|
||||
"@push.rocks/smarttime": "^4.0.6",
|
||||
"@types/diff": "^5.2.1",
|
||||
"@types/minimatch": "^5.1.2",
|
||||
"diff": "^5.2.0",
|
||||
"isomorphic-git": "^1.25.10"
|
||||
"@push.rocks/smarttime": "^4.1.1",
|
||||
"@types/diff": "^8.0.0",
|
||||
"diff": "^8.0.2",
|
||||
"isomorphic-git": "^1.32.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^2.1.80",
|
||||
"@git.zone/tsrun": "^1.2.44",
|
||||
"@git.zone/tstest": "^1.0.90",
|
||||
"@push.rocks/tapbundle": "^5.0.23"
|
||||
"@git.zone/tsbuild": "^2.6.4",
|
||||
"@git.zone/tsrun": "^1.3.3",
|
||||
"@git.zone/tstest": "^2.3.2"
|
||||
},
|
||||
"private": false,
|
||||
"files": [
|
||||
@@ -65,5 +63,6 @@
|
||||
],
|
||||
"browserslist": [
|
||||
"last 1 chrome versions"
|
||||
]
|
||||
],
|
||||
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
|
||||
}
|
||||
|
7853
pnpm-lock.yaml
generated
7853
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
onlyBuiltDependencies:
|
||||
- esbuild
|
||||
- mongodb-memory-server
|
||||
- puppeteer
|
249
readme.md
249
readme.md
@@ -1,121 +1,222 @@
|
||||
# @push.rocks/smartgit
|
||||
smart wrapper for nodegit
|
||||
|
||||
## Install
|
||||
To install @push.rocks/smartgit, use the following command with npm:
|
||||
> 🚀 **Modern Git operations for Node.js** - A powerful TypeScript wrapper around isomorphic-git that makes repository management and analysis a breeze
|
||||
|
||||
[](https://badge.fury.io/js/@push.rocks%2Fsmartgit)
|
||||
[](https://www.typescriptlang.org/)
|
||||
|
||||
## ✨ What is SmartGit?
|
||||
|
||||
SmartGit is a sophisticated, promise-based Git toolkit designed for Node.js applications. Built on top of `isomorphic-git`, it provides a clean, intuitive API for repository management, diff analysis, and commit history exploration. Perfect for automation tools, CI/CD pipelines, and any application that needs to interact with Git repositories programmatically.
|
||||
|
||||
## 🎯 Key Features
|
||||
|
||||
- **🔧 Repository Management** - Create, clone, and open repositories with ease
|
||||
- **🌐 Remote Operations** - Manage remotes and push changes effortlessly
|
||||
- **📊 Diff Analysis** - Get detailed diffs of uncommitted changes
|
||||
- **📚 Commit History** - Extract commit messages with metadata and version tracking
|
||||
- **⚡ Async/Await** - Modern promise-based API throughout
|
||||
- **🛡️ TypeScript First** - Full type safety and IntelliSense support
|
||||
- **🎯 Production Ready** - Battle-tested and actively maintained
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
```bash
|
||||
npm install @push.rocks/smartgit --save
|
||||
```
|
||||
# Using pnpm (recommended)
|
||||
pnpm install @push.rocks/smartgit
|
||||
|
||||
Or if you prefer using yarn:
|
||||
# Using npm
|
||||
npm install @push.rocks/smartgit
|
||||
|
||||
```bash
|
||||
# Using yarn
|
||||
yarn add @push.rocks/smartgit
|
||||
```
|
||||
|
||||
Make sure you have `node` installed on your system to use this package.
|
||||
|
||||
## Usage
|
||||
|
||||
This guide assumes familiarity with TypeScript and basic Git operations. The `@push.rocks/smartgit` module offers a sophisticated, promise-based interface to interact with Git repositories in a Node.js environment, abstracting over the `isomorphic-git` library and adding additional functionality.
|
||||
|
||||
### Setting Up
|
||||
|
||||
First, you need to import `Smartgit` and other necessary classes from the package. This is also when you'd typically configure any additional settings or dependencies required by your project.
|
||||
## 🚀 Quick Start
|
||||
|
||||
```typescript
|
||||
import { Smartgit } from '@push.rocks/smartgit';
|
||||
|
||||
// Initialize the Smartgit instance
|
||||
// Initialize SmartGit
|
||||
const smartgit = new Smartgit();
|
||||
await smartgit.init();
|
||||
|
||||
// Clone a repository
|
||||
const repo = await smartgit.createRepoByClone(
|
||||
'https://github.com/username/repo.git',
|
||||
'./local-repo'
|
||||
);
|
||||
|
||||
console.log('🎉 Repository cloned successfully!');
|
||||
```
|
||||
|
||||
### Creating, Cloning, and Opening Repositories
|
||||
## 📖 Usage Guide
|
||||
|
||||
With `Smartgit`, you can easily manage local repositories by creating new ones, cloning existing repositories, or opening an already existing local repository.
|
||||
### 🏗️ Repository Operations
|
||||
|
||||
#### Creating a New Repository
|
||||
|
||||
```typescript
|
||||
const pathToNewRepo = '/path/to/your/new/repo';
|
||||
const newRepo = await smartgit.createRepoByInit(pathToNewRepo);
|
||||
const repo = await smartgit.createRepoByInit('./my-new-repo');
|
||||
```
|
||||
|
||||
#### Cloning a Repository
|
||||
#### Cloning from Remote
|
||||
|
||||
```typescript
|
||||
const cloneUrl = 'https://github.com/yourusername/your-repo.git';
|
||||
const pathToClone = '/path/to/clone/repo';
|
||||
const clonedRepo = await smartgit.createRepoByClone(cloneUrl, pathToClone);
|
||||
const repo = await smartgit.createRepoByClone(
|
||||
'https://github.com/octocat/Hello-World.git',
|
||||
'./hello-world'
|
||||
);
|
||||
```
|
||||
|
||||
#### Opening an Existing Repository
|
||||
#### Opening Existing Repository
|
||||
|
||||
```typescript
|
||||
const pathToExistingRepo = '/path/to/your/existing/repo';
|
||||
const existingRepo = await smartgit.createRepoByOpen(pathToExistingRepo);
|
||||
const repo = await smartgit.createRepoByOpen('./existing-repo');
|
||||
```
|
||||
|
||||
### Working with Git Operations
|
||||
### 🌐 Working with Remotes
|
||||
|
||||
`Smartgit` simplifies common Git operations, making it easy to execute commands like add, commit, push, and more programmatically.
|
||||
|
||||
#### Adding Changes
|
||||
|
||||
To stage changes, you can add all changes or specify particular files.
|
||||
#### List All Remotes
|
||||
|
||||
```typescript
|
||||
// Add all changes to staging
|
||||
await existingRepo.addAll();
|
||||
|
||||
// Or specify particular files
|
||||
await existingRepo.add(['file1.txt', 'path/to/file2.txt']);
|
||||
```
|
||||
|
||||
#### Committing Changes
|
||||
|
||||
Once changes are staged, you can commit them.
|
||||
|
||||
```typescript
|
||||
await existingRepo.commit('Your commit message');
|
||||
```
|
||||
|
||||
#### Pushing to a Remote
|
||||
|
||||
Before pushing, ensure a remote is set up correctly, then push your changes.
|
||||
|
||||
```typescript
|
||||
await existingRepo.ensureRemote('origin', 'https://github.com/yourusername/your-repo.git');
|
||||
await existingRepo.pushBranchToRemote('main', 'origin');
|
||||
```
|
||||
|
||||
### Advanced Features
|
||||
|
||||
`Smartgit` also supports more advanced Git functionalities, such as dealing with branches, managing remotes, and checking repository status.
|
||||
|
||||
#### Listing Remotes
|
||||
|
||||
```typescript
|
||||
const remotes = await existingRepo.listRemotes();
|
||||
const remotes = await repo.listRemotes();
|
||||
console.log(remotes);
|
||||
// Output: [{ remote: 'origin', url: 'https://github.com/...' }]
|
||||
```
|
||||
|
||||
#### Working with Branches
|
||||
#### Ensure Remote Exists
|
||||
|
||||
Branch management such as creating new branches or checking out existing ones can be done through the underlying `isomorphic-git` functions, with `Smartgit` making the setup and usage straightforward.
|
||||
```typescript
|
||||
await repo.ensureRemote('origin', 'https://github.com/username/repo.git');
|
||||
```
|
||||
|
||||
### Practical Tips
|
||||
#### Get Remote URL
|
||||
|
||||
- When dealing with asynchronous operations, especially in sequences that depend on the outcome of previous steps (e.g., staging, committing, and pushing), ensure proper error handling, either using `.then().catch()` chains or `try/catch` blocks with async/await.
|
||||
- For complex Git workflows, consider combining `Smartgit`'s capabilities with other Node.js modules or scripts to automate and streamline your processes.
|
||||
```typescript
|
||||
const originUrl = await repo.getUrlForRemote('origin');
|
||||
console.log(`📡 Origin URL: ${originUrl}`);
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
#### Push to Remote
|
||||
|
||||
`@push.rocks/smartgit` provides a versatile and powerful toolkit for Git operations in Node.js applications. By abstracting the complexities of interacting with Git repositories, it enables developers to focus more on developing their logic and less on the intricacies of Git commands. Whether you're managing local repositories, automating deployment workflows, or integrating Git operations into your applications, `Smartgit` offers a comprehensive set of features to address your needs.
|
||||
```typescript
|
||||
await repo.pushBranchToRemote('main', 'origin');
|
||||
console.log('✅ Changes pushed successfully!');
|
||||
```
|
||||
|
||||
For further examples, contributions, and issues, please refer to the [project's repository](https://gitlab.com/pushrocks/smartgit) and consider contributing to or starring the project if you find it useful.
|
||||
### 📊 Diff Analysis
|
||||
|
||||
Get a detailed diff of uncommitted changes (perfect for code review automation):
|
||||
|
||||
```typescript
|
||||
const diffs = await repo.getUncommittedDiff(['node_modules/*', '*.log']);
|
||||
|
||||
diffs.forEach(diff => {
|
||||
console.log('📝 File changes:');
|
||||
console.log(diff);
|
||||
});
|
||||
```
|
||||
|
||||
### 📚 Commit History Analysis
|
||||
|
||||
Extract commit history with package.json version tracking:
|
||||
|
||||
```typescript
|
||||
const history = await repo.getAllCommitMessages();
|
||||
|
||||
history.forEach(commit => {
|
||||
console.log(`🕐 ${commit.date} | v${commit.version} | ${commit.message}`);
|
||||
});
|
||||
|
||||
// Example output:
|
||||
// 🕐 2024-01-15 | v1.2.3 | feat: add new authentication method
|
||||
// 🕐 2024-01-14 | v1.2.2 | fix: resolve memory leak in parser
|
||||
```
|
||||
|
||||
## 🛠️ Advanced Usage
|
||||
|
||||
### Error Handling
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const repo = await smartgit.createRepoByClone(invalidUrl, './test');
|
||||
} catch (error) {
|
||||
console.error('❌ Clone failed:', error.message);
|
||||
}
|
||||
```
|
||||
|
||||
### Working with Multiple Repositories
|
||||
|
||||
```typescript
|
||||
const smartgit = new Smartgit();
|
||||
await smartgit.init();
|
||||
|
||||
const repositories = [
|
||||
await smartgit.createRepoByOpen('./repo1'),
|
||||
await smartgit.createRepoByOpen('./repo2'),
|
||||
await smartgit.createRepoByOpen('./repo3')
|
||||
];
|
||||
|
||||
// Analyze all repositories
|
||||
for (const repo of repositories) {
|
||||
const remotes = await repo.listRemotes();
|
||||
console.log(`📂 Repository has ${remotes.length} remotes`);
|
||||
}
|
||||
```
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
SmartGit is built with a clean, modular architecture:
|
||||
|
||||
- **`Smartgit`** - Main entry point and repository factory
|
||||
- **`GitRepo`** - Individual repository operations and analysis
|
||||
- **`isomorphic-git`** - Underlying Git implementation
|
||||
- **Environment Detection** - Automatic Node.js environment setup
|
||||
|
||||
## 🎯 Use Cases
|
||||
|
||||
- **🤖 Automation Scripts** - Automate repository management and analysis
|
||||
- **🔄 CI/CD Pipelines** - Repository operations in build processes
|
||||
- **📊 Code Analysis Tools** - Extract commit data and diff analysis
|
||||
- **🛠️ Developer Tools** - Build Git-powered development utilities
|
||||
- **📱 Release Management** - Track versions and generate changelogs
|
||||
|
||||
## 🔧 Requirements
|
||||
|
||||
- **Node.js** 16+ (Browser support not available)
|
||||
- **Git repository** access (for clone operations)
|
||||
- **TypeScript** 4+ (recommended)
|
||||
|
||||
## 🤝 API Reference
|
||||
|
||||
### Smartgit Class
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `init()` | Initialize the SmartGit instance | `Promise<void>` |
|
||||
| `createRepoByInit(dir)` | Create new repository | `Promise<GitRepo>` |
|
||||
| `createRepoByClone(url, dir)` | Clone repository | `Promise<GitRepo>` |
|
||||
| `createRepoByOpen(dir)` | Open existing repository | `Promise<GitRepo>` |
|
||||
|
||||
### GitRepo Class
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `listRemotes()` | List all remotes | `Promise<{remote: string, url: string}[]>` |
|
||||
| `ensureRemote(name, url)` | Ensure remote exists | `Promise<void>` |
|
||||
| `getUrlForRemote(name)` | Get URL for remote | `Promise<string>` |
|
||||
| `pushBranchToRemote(branch, remote)` | Push branch to remote | `Promise<void>` |
|
||||
| `getUncommittedDiff(excludeFiles?)` | Get uncommitted changes | `Promise<string[]>` |
|
||||
| `getAllCommitMessages()` | Get commit history | `Promise<CommitInfo[]>` |
|
||||
|
||||
## 💡 Pro Tips
|
||||
|
||||
- **🔧 Always call `init()`** before using any repository operations
|
||||
- **📁 Use absolute paths** for repository directories when possible
|
||||
- **🚫 Exclude large files** from diff analysis using the `excludeFiles` parameter
|
||||
- **⚡ Batch operations** when working with multiple repositories
|
||||
- **🛡️ Handle errors gracefully** - network issues can cause clone operations to fail
|
||||
|
||||
## License and Legal Information
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as smartgit from '../ts/index.js';
|
||||
|
||||
import * as smartpath from '@push.rocks/smartpath';
|
||||
|
@@ -1,40 +1,90 @@
|
||||
import * as plugins from './smartgit.plugins.js';
|
||||
import { GitRepo } from './smartgit.classes.gitrepo.js';
|
||||
|
||||
interface IEnvDeps {
|
||||
fs: typeof import('fs') | null;
|
||||
http: any | null; // isomorphic-git http interface
|
||||
}
|
||||
|
||||
/**
|
||||
* class Smartgit provides a high-level interface for git operations
|
||||
* Must be initialized before use by calling init()
|
||||
*/
|
||||
export class Smartgit {
|
||||
public smartenvInstance = new plugins.smartenv.Smartenv();
|
||||
public envDeps: {
|
||||
fs: any;
|
||||
http: any;
|
||||
} = {
|
||||
public envDeps: IEnvDeps = {
|
||||
fs: null,
|
||||
http: null,
|
||||
};
|
||||
|
||||
constructor() {}
|
||||
|
||||
public async init() {
|
||||
/**
|
||||
* initializes the Smartgit instance with required environment dependencies
|
||||
* Must be called before using any repository methods
|
||||
*/
|
||||
public async init(): Promise<void> {
|
||||
try {
|
||||
if (this.smartenvInstance.isNode) {
|
||||
this.envDeps.fs = await this.smartenvInstance.getSafeNodeModule('fs');
|
||||
this.envDeps.http = await this.smartenvInstance.getSafeNodeModule(
|
||||
'isomorphic-git/http/node/index.js'
|
||||
'isomorphic-git/http/node'
|
||||
);
|
||||
} else {
|
||||
throw new Error('currently only node.js is supported.');
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to initialize Smartgit: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async createRepoByClone(fromUrlArg: string, toDirArg: string) {
|
||||
private ensureInitialized(): void {
|
||||
if (!this.envDeps.fs || !this.envDeps.http) {
|
||||
throw new Error('Smartgit must be initialized before use. Call init() first.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a new GitRepo instance by cloning from a remote URL
|
||||
* @param fromUrlArg the URL to clone from
|
||||
* @param toDirArg the directory to clone into
|
||||
* @returns Promise<GitRepo> the created repository instance
|
||||
*/
|
||||
public async createRepoByClone(fromUrlArg: string, toDirArg: string): Promise<GitRepo> {
|
||||
this.ensureInitialized();
|
||||
try {
|
||||
const repo = await GitRepo.fromCloningIntoDir(this, fromUrlArg, toDirArg);
|
||||
return repo;
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async createRepoByInit(dirArg: string) {
|
||||
/**
|
||||
* creates a new GitRepo instance by initializing a new repository in a directory
|
||||
* @param dirArg the directory to initialize the repository in
|
||||
* @returns Promise<GitRepo> the created repository instance
|
||||
*/
|
||||
public async createRepoByInit(dirArg: string): Promise<GitRepo> {
|
||||
this.ensureInitialized();
|
||||
try {
|
||||
const repo = await GitRepo.fromCreatingRepoInDir(this, dirArg);
|
||||
return repo;
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to initialize repository: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async createRepoByOpen(dirArg: string) {
|
||||
/**
|
||||
* creates a new GitRepo instance by opening an existing repository in a directory
|
||||
* @param dirArg the directory containing the existing repository
|
||||
* @returns Promise<GitRepo> the opened repository instance
|
||||
*/
|
||||
public async createRepoByOpen(dirArg: string): Promise<GitRepo> {
|
||||
this.ensureInitialized();
|
||||
try {
|
||||
const repo = await GitRepo.fromOpeningRepoDir(this, dirArg);
|
||||
return repo;
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to open repository: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user