GithubHelp home page GithubHelp logo

rlugojr / repofs Goto Github PK

View Code? Open in Web Editor NEW

This project forked from gitbookio/repofs

0.0 2.0 0.0 602 KB

Simple and unified API to manipulate Git repositories

License: Apache License 2.0

JavaScript 98.14% Shell 1.86%

repofs's Introduction

repofs

NPM version Build Status

This module provides a simple and unified API to manipulate Git repositories on GitHub. This module can be use in Node.JS and in the browser.

It allows more complex operations than the Contents API using the Git Data API.

It is powered by an immutable model. Async operations are Promise-based.

Installation

$ npm install repofs

How to use it?

To use repofs in the browser, include it using browserify/webpack.

var repofs = require('repofs');

Initialize a driver instance, a driver represents the communication layer between repofs and the real git repository.

var driver = repofs.GitHubDriver({
    repository: 'MyUsername/myrepository',
    username: 'MyUsername',
    token: 'MyPasswordOrMyApiToken'
});

Start with an empty RepositoryState

The first step is to create an instance of RepositoryState:

var repoState = repofs.RepositoryState.createEmpty();

Fetch the list of branches

After creating a RepositoryState, the next step is to fetch the list of existing branches.

repofs.RepoUtils.fetchBranches(repoState, driver)
.then(function (newRepoState) {
    var branches = newRepoState.getBranches(); // List<Branch>
    ...
})

Checkout a branch

Once the branches are fetched, you can checkout one. This requires to fetch it first using repofs.RepoUtils.fetchTree. This overrides any existing working tree for this branch. The repofs.RepoUtils.checkout operation is always sync.

var branch = repoState.getBranch('master');

repofs.RepoUtils.fetchTree(repoState, driver, branch)
.then(function (repoState) {
    var checkoutState = repofs.RepoUtils.checkout(repoState, driver, branch);
    ...
})

Quick initialization

There is a short way to initialize a RepositoryState from a driver, that will fetch the list of the branches, then fetch and checkout master or the first available branch.

repofs.RepoUtils.initialize(driver)
.then(function (repoState) {
    // repoState checked out on master
    ...
});

Reading files

Reading a file requires to fetch the content from the remote repository inside the RepositoryState (See Caching):

repofs.WorkingUtil.fetchFile(repoState, driver, 'README.md')
.then(function(newRepoState) {
    ...
})

Then the content can be accessed using sync methods:

// Read as a blob
var blob = repofs.FileUtils.read(repoState, 'README.md');

// Read as a String
var content = repofs.FileUtils.readAsString(repoState, 'README.md');

Listing files

repofs keeps the whole trees in the different WorkingStates, you can access the whole tree as a flat list...

var workingState = repoState.getCurrentState();
var treeEntries = workingState.getTreeEntries();

... or as an immutable tree structure (a TreeNode<File>):

var dir = '.' // root
var rootTree = repofs.TreeUtils.get(repoState, dir);

Working with files

Create a new file:

var newRepoState = repofs.FileUtils.create(repoState, 'API.md');

Write/Update the file

var newRepoState = repofs.FileUtils.write(repoState, 'API.md', 'content');

Remove the file

var newRepoState = repofs.FileUtils.remove(repoState, 'API.md');

Rename/Move the file

var newRepoState = repofs.FileUtils.move(repoState, 'API.md', 'API2.md');

Working with directories

List files in the directory

var pathList = repofs.DirUtils.read(repoState, 'myfolder');

Remove the directory

var newRepoState = repofs.DirUtils.remove(repoState, 'myfolder');

Rename/Move the directory

var newRepoState = repofs.DirUtils.move(repoState, 'myfolder', 'myfolder2');

Changes

Until being commited, repofs keeps a record of changes per files.

Revert all non-commited changes using:

var newRepoState = repofs.ChangeUtils.revertAll(repoState);

Or revert changes for a specific file or directory:

// Revert change on a specific file
var newRepoState = repofs.ChangeUtils.revertForFile(repoState, 'README.md');

// Revert change on a directory
var newRepoState = repofs.ChangeUtils.revertForDir(repoState, 'src');

Commiting changes

// Create an author / committer
var john = repofs.Author.create('John Doe', '[email protected]');

// Create a CommitBuilder to define the commit
var commitBuilder = repofs.CommitUtils.prepare(repoState, {
    author: john,
    message: 'Initial commit'
});

// Flush commit using the driver
repofs.CommitUtils.flush(repoState, driver, commitBuilder)
.then(function(newRepoState) {
    // newRepoState updated with new working tree
    ...
});

Manipulating branches

 // Create a branch from current branch
 repofs.BranchUtils.create(repoState, driver, 'develop')
 .then(function (newRepoState) {
    var develop = newRepoState.getBranch('develop');
});
 // Remove a branch
 repofs.BranchUtils.remove(repoState, driver, branch)
 .then(function (newRepoState) {
    ...
});

Non fast forward commits

Flushing a commit can fail with an ERRORS.NOT_FAST_FORWARD code.

// Flush commit using the driver
repofs.CommitUtils.flush(repoState, driver, commitBuilder)
.then(function success(newRepoState) {
    ...
}, function failure(err) {
    // Catch non fast forward errors
    if(err.code !== repofs.ERRORS.NOT_FAST_FORWARD) {
        throw err;
    }
    ...
});

Non fast forward errors contains the created commit (that is currently not linked to any branch). This allows you to attempt to merge this commit back into the current branch:

... function fail(err) {
    // Catch non fast forward errors
    if(err.code !== repofs.ERRORS.NOT_FAST_FORWARD) {
        throw err;
    }
    // The created commit
    var commit = err.commit;
    // Attempt automatic merge
    var from = commit.getSha();
    var into = repoState.getCurrentBranch();
    return repofs.BranchUtils.merge(repoState, driver, from, into)
    .then(function success(repoState) {
        ...
    });
}

Merging

repofs.BranchUtils.merge allows to automatically merge a commit or a branch, into another branch.

// from is either a Branch or a commit SHA string
repofs.BranchUtils.merge(repoState, driver, from, into)
.then(function success(repoState) {
    ...
});

Merge conflicts

But conflicts can happen when the automatic merge failed. For example, after merging two branches, or after merging a non fast forward commit. It is possible then to solve the conflicts manually:

repofs.BranchUtils.merge(repoState, driver, from, into)
.then(function success(repoState) {
    ...
}, function failure(err) {
    // Catch merge conflict errors
    if(err.code !== repofs.ERRORS.CONFLICT) {
        throw err;
    }
    solveConflicts(repoState, driver, from, into)
});

The function solveConflicts would compute the TreeConflict representing all the conflicts between from and into references, solve it in some ways, and make a merge commit. Here is an example of such function:

function solveConflicts(repoState, driver, from, into) {
    return repofs.ConflictUtils.compareRefs(driver, base, head)
    .then(function (treeConflict) {
        // Solve the list of conflicts in some way, for example by
        // asking a user to do it manually.
        var solvedConflicts // Map<Path, Conflict>
            = solve(treeConflict.getConflicts());

        // Create a solved conflict tree
        var solvedTreeConflict // TreeConflict
            = repofs.ConflictUtils.solveTree(treeConflict, solvedConflicts);

        // The SHAs of the parent commits
        var parentShas = [from.getSha(), into.getSha()];
        // Create the merge commit
        var commitBuilder = repofs.ConflictUtils.mergeCommit(solvedTreeConflict, parents);

        // Flush it on the target branch
        return repofs.CommitUtils.flush(repoState, driver, commitBuilder, {
            branch: into
        });
    });
}

Remotes operations

When using a compatible API, you can also deal with remotes on the repository.

List remotes

repofs.RemoteUtils.list(driver)
.then(function (remotes) {
    // remotes is an Array of remote:
    // {
    //   name,
    //   url
    // }
});

Edit remotes

repofs.RemoteUtils.edit(driver, name, url)
.then(function () {
    // Remote edited
});

Pulling

You can update a branch to the state of the same branch on a remote, and get an updated RepositoryState with:

var master = repoState.getBranch('master');
var remote = {
    name: 'origin'
};

repofs.RemoteUtils.pull(repoState, driver, {
    branch: master,
    remote: remote,
    auth: {
        username: Shakespeare,
        password: 'f00lish wit'
    }
})
.then(function (newRepoState) {
    ...
})

Pushing

You can push a branch to a remote:

var master = repoState.getBranch('master');
var remote = {
    name: 'origin'
};

repofs.RemoteUtils.push(repoState, driver, {
    branch: master,
    remote: remote,
    auth: {
        username: Shakespeare,
        password: 'f00lish wit'
    }
})
.then(function () {
    // Pushed
})

Contributing

Run tests

You can run all the tests by providing a GITHUB_TOKEN with permission to create and write to a GitHub repository, and running npm run test.

You can run tests with GitHub as a backend npm run test-github, or Uhub as a backend npm run test-uhub.

Finally, you can run the tests without testing the API through the drivers by running npm run test-no-api.

repofs's People

Contributors

samypesse avatar soreine avatar mklabs avatar aarono avatar

Watchers

Ray Lugo, Jr. avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.