Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Local promise-returning git command wrappers
You can install and run this tool as a stand alone CLI application.
npm install -g ggit
ggit --help
note ggit-last
tool has been moved to
git-last repo.
var clone = require('ggit').cloneRepo;
clone({
url: 'git@github.com:bahmutov/test-next-updater.git',
folder: 'folder to create, should not exist yet'
}).then(function () {
console.log('cloned repo to destination folder');
});
var exec = require('ggit').exec;
var cmd = 'rm -rf folder';
var verbose = true;
exec(cmd, verbose).then(function () {
console.log('removed folder');
});
Finds last person who has touched specific line in a file
var blame = require('ggit').blame;
blame(filename, lineNumber).then(function (info) {
/*
info is object with fields like
{ commit: '6e65f8ec5ed63cac92ed130b1246d9c23223c04e',
author: 'Gleb Bahmutov',
committer: 'Gleb Bahmutov',
summary: 'adding blame feature',
filename: 'test/blame.js',
line: 'var blame = require(\'../index\').blame;' }
*/
});
Equivalent to porcelain git output: see git-blame
Returns true
if given path is tracked in the repo.
var isTracked = require('ggit').isTracked;
isTracked(filename).then(function (result) {
// result is true or false
});
Returns true
if there are local uncommitted stages
var changed = require('ggit').hasChanges;
changed().then(function (result) {
// result is true or false
});
Commit any changes with a given message. Second argument is optional and will be added after a blank line to the short main message.
var commit = require('ggit').commit;
commit('added foo', 'long text').then(function () {
// after commit
});
You can pass the entire message if wanted as first argument
var fullMessage = 'first line\n\nbody of message\n';
commit(fullMessage).then(...);
Push commits to the remote
var psuh = require('ggit').psuh;
psuh().then(function () {
// after the push
});
Returns list of commits in the given folder as a list or object
// commits.all - gets all commits
var commits = require('ggit').commits;
commits.all(gitRepoFolder)
.then(R.take(2))
.then(console.table)
.done();
// commits.byId - transforms list of commits into object
// where keys = ids, values = messages
// For example to get an object with 2 commit ids as keys
commits.all(gitRepoFolder)
.then(R.take(2))
.then(commits.byId)
.then(console.log)
.done();
Each object has at least 'id', 'message' and (maybe empty) 'body' properties.
You can also return just the commits starting from the last version tag (which usually starts with 'v'). This is useful for semantic release code.
var commits = require('ggit').commits;
commits.afterLastTag()
.then(function (list) { ... })
You can get commits after certain SHA
var commits = require('ggit').commits;
commits.after('439...')
.then(function (list) { ... })
Returns all tracked source files in the given folder matching pattern. Both folder and pattern are optional.
require('ggit')
.trackedFiles(__dirname, '*.js', options)
.then(function (list) {
console.log('javascript tracked in the current folder are');
console.log(list);
})
.done();
The options
argument is optional, and is passed directly to the
glob package that does file discovery.
The only important option to use is { dot: true }
- if you want to find the
filenames that start with .
. For example to find ALL files in the repo call
require('ggit')
.trackedFiles(__dirname, '**', { dot: true })
// returns .gitignore, .travis.yml, index.js etc
Returns all untracked source files in the repo.
require('ggit')
.untrackedFiles()
.then(function (list) {
// list is Array of strings, could be empty
console.log('untracked files are');
console.log(list);
})
.done();
Returns an object where for each key (filename) there is a list of commits for each line.
var perLine = require('ggit').commitPerLine;
perLine(['foo.js', 'bar.js']).then(function (result) {
/*
{
'foo.js': [{
commit: '3c6b01eb3c96db1cbdf277904545107ef97cbb56',
author: 'Gleb Bahmutov',
committer: 'Gleb Bahmutov',
summary: 'cool commit',
filename: 'foo.js',
line: '// actual source line'
},
...
}],
'bar.js': [...]
}
*/
});
Returns info for a specific commit - number of lines changed, deleted.
Same as $ git show --numstat <id>
.
require('ggit')
.numstat('5d3ee3')
.then(function (result) {
/* result is
{
commit: <full commit SHA>,
author:
message:
date:
changes: {
'filename 1': {
filename: 'filename 1',
added: 10,
deleted: 3
},
...
}
}
*/
})
.done();
Returns last commit id
require('ggit')
.lastCommitId()
.then(function (str) {
// str is full SHA id string
})
.done();
You can pass options object as in lastCommitId(options)
where
file
name.When saving into a file, it will grab version from package.json
(if the file exists),
current ISO timestamp + Eastern Standard Timezon timestamp, so the full JSON will look
something like this
{
"id": "d3d9f1656ded06c490b12a9ec5636d80dfd932eb",
"short": "d3d9f16",
"savedAt": "2017-08-24T18:58:27.210Z",
"EST": "2017-08-24T14:58:27-04:00",
"version": "1.2.3" ,
"branch": "master"
}
If you pass option {message: true}
the output will also have cropped commit subject string,
making finding the deploy easier.
{
"id": "d3d9f1656ded06c490b12a9ec5636d80dfd932eb",
"short": "d3d9f16",
"savedAt": "2017-08-24T18:58:27.210Z",
"EST": "2017-08-24T14:58:27-04:00",
"message": "feat(build): ad...",
"version": "1.2.3"
}
Resolves with the current branch name
require('ggit').branchName()
.then(function (name) {
// name = "master" or whatever
});
Returns list of modified files
var changedFiles = require('ggit').changedFiles;
changedFiles()
.then(function (files) {})
.catch(function (error) {});
The object files
groups filenames by modification property
{
A: [...], // list of added files
C: [...], // list of copied files
M: [...], // list of modified files
D: [...] // list of deleted files
}
// each item in the list is
{
diff: 'A' // or C, M, D
name: 'src/something.js' // relative to the repo root
filename: 'full path',
before: 'file contents', // if available (for example M, D)
after: 'file contents' // if available (for A, M)
}
This is a wrapper around two commands git diff --name-status --diff-filter=ACMD
and git status --porcelain
Returns list of unique files modified / added / deleted after given commit. The commits are limited to specific branch (usually "master") to avoid mixing up multiple branches.
var changedFilesAfter = require('ggit').changedFilesAfter;
changedFilesAfter('a12f55f', 'master')
.then(console.log)
.catch(console.error);
/*
something like
[ 'README.md',
'docs/commits.md',
'src/commits.js',
'src/get-one-line-log.js',
'package.json',
'src/last-commit-id.js' ]
*/
Returns the contents of a file at some point
var fileContents = require('ggit').fileContents;
fileContents(filename).then(function (text) { ... });
Same as git show <at>:<name>
Returns the contents of the Git current commit message, usually for validation before the commit.
require('ggit').commitMessage()
.then(function (text) {
// do something with the message
},
function () {
// file not found
});
If you pass SHA, it will grab that commit's email, subject and body (if exists) and return as an object
require('ggit').commitMessage('4df4...')
.then(console.log)
/*
{
"email": "foo@email.com",
"subject": "something something",
"body": "more details about the commit\nanother line"
}
*/
Returns the root folder, equivalent to command
line git rev-parse --show-toplevel
require('ggit').getGitFolder()
.then(folder => {
...
})
Requires
git
>= 2.0
Returns list of tags in the given folder, including commit ids.
var tags = require('ggit').tags;
tags().then(function (list) {
/*
each object in list is like
{
"commit": "7756b5609c5aae651f267fa3fc00763bcd276bf6",
"tag": "v1.3.0"
}
*/
})
You can return just tags that start with "v" by passing
true
to tags
.
tags(true).then(function (list) {...})
Oldest tag is returns as first object, latest tag is the last object in the list.
If you have older git
(like Travis does), it will automatically try to
grab all the tags and sort them using
semantic sort
Requires
git
>= 2.7
Similar to tags
, branchTags
returns tags in the given folder,
but only those tags accessible from the current branch. Any tags
in the repository that point to a commit on another branch will
not be returned by branchTags
.
var branchTags = require('ggit').branchTags;
branchTags().then(function (list) {
/*
each object in list is like
{
"commit": "7756b5609c5aae651f267fa3fc00763bcd276bf6",
"tag": "v1.3.0"
}
*/
})
You can return just tags that start with "v" by passing
true
to branchTags
.
branchTags(true).then(function (list) {...})
Oldest tag is returned as first object, latest tag is the last object in the list.
Fetches remote tags from origin.
var fetchTags = require('ggit').fetchTags;
fetchTags().then(function () {
// should be same as running command
// git pull origin --tags
})
You can pass the branch name, by default will fetch from master
fetchTags('development')
Edit source, run unit tests, run end to end tests and push the code back to Github. The NPM publishing happens automatically using semantic release
npm test
npm run commit
git push
To debug problems, run the command with DEBUG=ggit
environment variable enabled
to see verbose logging.
Some of the unit tests rely on extracting private functions from modules
using scope magic with describe-it
,
which requires Node 4.2.2 and might not work with later Node versions.
Author: Gleb Bahmutov © 2015
License: MIT - do anything with the code, but don't blame uTest if it does not work.
Spread the word: tweet, star on github, etc.
Support: if you find any problems with this module, email / tweet / open issue on Github
FAQs
Local promise-returning git command wrappers
The npm package ggit receives a total of 10,219 weekly downloads. As such, ggit popularity was classified as popular.
We found that ggit demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.