Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sync-to-github

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sync-to-github - npm Package Compare versions

Comparing version 0.0.5 to 0.0.6

153

lib/sync.js

@@ -26,2 +26,5 @@ var GitHubApi = require('github');

* @option {string} message Message for committed changes
* @option {boolean} [preserveRepoFiles] Perform only additive changes to the
* target repo, i.e. do not delete existing files or directories inside
* `repoPath`.
* @option {string} [branch] Name of branch in repo to sync to, defaults

@@ -46,30 +49,14 @@ * to `master`. This branch must already exist in repo.

// TODO: support subdirectories and filtering by doing a traversal
// and building blobs and trees as we visit. That algo may look somewhat
// different from this one.
return Promise.resolve().then(function() {
// Create a tree holding the files
// TODO: support subdirectories and filtering by doing a traversal
// and building blobs and trees as we visit
return createTreeForSingleDir(gitData, options.localPath);
}).then(function(newTargetTree) {
return getLatestCommit(gitData, options.branch).then(function(commit) {
var treeCache = {};
return gitData('getTree', { sha: commit.tree.sha }).then(function(rootTree) {
return parentTreesForPath(gitData, treeCache, rootTree, pathParts);
return existingTreesForPath(gitData, rootTree, pathParts);
}).then(function(treesForPath) {
treesForPath.push(newTargetTree);
return createTreeForPath(gitData, treesForPath, pathParts);
return createNewTreeForPath(gitData, options, treesForPath, pathParts);
}).then(function(newRootTree) {
return gitData('createCommit', {
message: options.message,
tree: newRootTree.sha,
parents: [commit.sha]
});
}).then(function(newCommit) {
return gitData('updateReference', {
ref: 'heads/' + options.branch,
sha: newCommit.sha
});
}).then(function() {
if (options.pullToBranch) {
return createPullRequest(github, options);
}
return commitChanges(gitData, options, commit, newRootTree);
});

@@ -184,7 +171,9 @@ });

* @param localPath {string} Local path to read all files from.
* @param [baseTree] {object} Tree to base the new tree on.
* @returns {Promise<Object>} Tree in github for the newly created directory
* in the repository.
*/
function createTreeForSingleDir(gitData, localPath) {
function createTreeForSingleDir(gitData, localPath, baseTree) {
// For each file in the directory
var pathExists = {};
return fs.readdirAsync(localPath).then(function(filenames) {

@@ -213,2 +202,3 @@ return Promise.all(filenames.map(function(filename) {

}).then(function(response) {
pathExists[filename] = true;
return {

@@ -224,2 +214,10 @@ path: filename,

}).then(function(children) {
if (baseTree) {
// We're basing this tree off an existing one. Bring in any children from
// the base that were not created in the new tree.
children = children.concat(
treeChildrenForCreateRequest(baseTree).filter(function(child) {
return !pathExists[child.path];
}));
}
return gitData('createTree', { tree: children });

@@ -229,2 +227,37 @@ });

/**
* Recursively create the the new git tree that effects changes along the
* given path.
*
* @param gitData {function} Wrapper to call the `gitdata` endpoint.
* @param options {object} Options for the sync request
* @param treesForPath {object[]} Array of trees from root to deepest change,
* with the last element being the newest change.
* @param pathParts {string[]} Array of path components from root to deepest.
* @returns {Promise<Object>} Tree in github for the newly created directory
* in the repository.
*/
function createNewTreeForPath(gitData, options, treesForPath, pathParts) {
return Promise.resolve().then(function() {
var existingTree = null;
if (treesForPath.length === pathParts.length + 1) {
// If there is a tree for every part of the path, there will be one more
// tree than part because there is no path part for the root.
debug(options, 'Target path already exists');
existingTree = treesForPath.splice(-1)[0];
}
if (treesForPath.length === pathParts.length) {
return createTreeForSingleDir(
gitData, options.localPath,
(existingTree && options.preserveRepoFiles) ? existingTree : null);
} else {
throw new Error(
'Could not find existing parent dir for repo path: ' +
options.repoPath);
}
}).then(function(newTargetTree) {
treesForPath.push(newTargetTree);
return createTreeForPath(gitData, treesForPath, pathParts);
});
}

@@ -264,5 +297,3 @@ /**

var newTreeChildren = parentTree.tree.map(function(child) {
return _.pick(child, ['path', 'mode', 'type', 'sha']);
});
var newTreeChildren = treeChildrenForCreateRequest(parentTree);
return gitData('createTree', { tree: newTreeChildren }).then(function(newTree) {

@@ -277,2 +308,43 @@ return createTreeForPath(

/**
* @param tree {object} A tree object as received from github
* @returns {object[]} An array of tree entries that are appropriate to
* upload to github for a tree creation request.
*/
function treeChildrenForCreateRequest(tree) {
return tree.tree.map(function(child) {
return _.pick(child, ['path', 'mode', 'type', 'sha']);
});
}
/**
* Commit a new tree to the branch to make the sync effective.
*
* @param gitData {function}
* @param options {object}
* @param latestCommit {object} latest commit on branch
* @param newRootTree {object} new root tree to commit
* @returns {Promise} Complete when changes are committed
*/
function commitChanges(gitData, options, latestCommit, newRootTree) {
// TODO: perhaps do something more sophisticated / robust to collisions
// like branch and merge.
return Promise.resolve().then(function() {
return gitData('createCommit', {
message: options.message,
tree: newRootTree.sha,
parents: [latestCommit.sha]
});
}).then(function(newCommit) {
return gitData('updateReference', {
ref: 'heads/' + options.branch,
sha: newCommit.sha
});
}).then(function() {
if (options.pullToBranch) {
return createPullRequest(github, options);
}
});
}
/**
* @param gitData {function} Wrapper to call the `gitdata` endpoint.

@@ -290,17 +362,17 @@ * @param branchName {string} Name of the branch to get the latest commit for.

/**
* Fetch tree information along a path.
* Fetch tree information along a path, as far as it exists.
*
* @param gitData {function} Wrapper to call the `gitdata` endpoint.
* @param treeCache {object} Cache of path -> tree so we don't have to fetch
* the same tree multiple times from git. May be initialized to empty.
* @param rootTree {object} Tree from git representing the root of the repo.
* @param pathParts {string[]} Components of the path to get the trees for.
* @returns {Promise<Object[]>} Trees from root to the parent of the deepest
* component of `pathParts`.
* @param [treeCache] {object} Cache of path -> tree so we don't have to fetch
* the same tree multiple times from git. May be initialized to empty.
* @returns {Promise<Object[]>} Trees from root to the deepest existing
* component of `pathParts`. Will have a length <= `pathParts.length`
*/
function parentTreesForPath(gitData, treeCache, rootTree, pathParts) {
function existingTreesForPath(gitData, rootTree, pathParts, treeCache) {
treeCache = treeCache || {};
treeCache[rootTree.sha] = rootTree;
if (pathParts.length <= 1) {
// We stop here. The deepest component may not even exist, but we don't
// need to return it since we're getting parents.
if (pathParts.length === 0) {
// No where left to go!
return [rootTree];

@@ -316,3 +388,4 @@ }

if (!nextTreeInfo) {
throw new Error('Path not found in tree: ' + path);
// This is the end of the line.
return [rootTree];
}

@@ -322,3 +395,3 @@

return getTree(gitData, treeCache, nextTreeInfo.sha).then(function(nextTree) {
return parentTreesForPath(gitData, treeCache, nextTree, remainingPath);
return existingTreesForPath(gitData, nextTree, remainingPath, treeCache);
}).then(function(subTree) {

@@ -369,3 +442,3 @@ return [rootTree].concat(subTree);

// an outstanding pull request.
// TODO: update pull request with new message
// TODO: update pull request with new message?
console.log('Pull request for branch already exists, ignoring.');

@@ -380,3 +453,3 @@ } else {

syncToGitHub: syncToGitHub,
parentTreesForPath: parentTreesForPath
existingTreesForPath: existingTreesForPath
};
{
"name": "sync-to-github",
"version": "0.0.5",
"version": "0.0.6",
"description": "Easily sync a directory of files to a GitHub repo using the GitHub API",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc