lib/repository.js
function performRebase(
  repository,
  rebase,
  signature,
  beforeNextFn,
  beforeFinishFn
) {
  var beforeNextFnResult;

  /* In the case of FF merges and a beforeFinishFn, this will fail
   * when looking for 'rewritten' so we need to handle that case.
   */
  function readRebaseMetadataFile(fileName, continueOnError) {
    return fse.readFile(
      path.join(repository.path(), "rebase-merge", fileName),
      { encoding: "utf8" }
    )
      .then(fp.trim)
      .catch(function(err) {
        if (continueOnError) {
          return null;
        }
        throw err;
      });
  }

  function calcHeadName(input) {
    return input.replace(/refs\/heads\/(.*)/, "$1");
  }

  function getPromise() {
    return rebase.next()
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        if (index.hasConflicts()) {
          throw index;
        }

        return rebase.commit(null, signature);
      })
      .then(function() {

        return performRebase(
          repository,
          rebase,
          signature,
          beforeNextFn,
          beforeFinishFn
        );
      })
      .catch(function(error) {
        if (error && error.errno === NodeGit.Error.CODE.ITEROVER) {
          const calcRewritten = fp.cond([
            [fp.isEmpty, fp.constant(null)],
            [fp.stubTrue, fp.flow([
              fp.split("\n"),
              fp.map(fp.split(" "))
            ])]
          ]);

          const beforeFinishFnPromise = !beforeFinishFn ?
            Promise.resolve() :
            Promise.all([
              readRebaseMetadataFile("onto_name"),
              readRebaseMetadataFile("onto"),
              readRebaseMetadataFile("head-name").then(calcHeadName),
              readRebaseMetadataFile("orig-head"),
              readRebaseMetadataFile("rewritten", true).then(calcRewritten)
            ])
              .then(function([
                ontoName,
                ontoSha,
                originalHeadName,
                originalHeadSha,
                rewritten
              ]) {
                return beforeFinishFn({
                  ontoName,
                  ontoSha,
                  originalHeadName,
                  originalHeadSha,
                  rebase,
                  rewritten
                });
              });

          return beforeFinishFnPromise
            .then(function() {
              return rebase.finish(signature);
            });
        } else {
          throw error;
        }
      });
  }

  if(beforeNextFn) {
    beforeNextFnResult = beforeNextFn(rebase);
    // if beforeNextFn returns a promise, chain the promise
    return Promise.resolve(beforeNextFnResult)
      .then(getPromise);
  }

  return getPromise();
}
function performRebase(
  repository,
  rebase,
  signature,
  beforeNextFn,
  beforeFinishFn
) {
  var beforeNextFnResult;

  /* In the case of FF merges and a beforeFinishFn, this will fail
   * when looking for 'rewritten' so we need to handle that case.
   */
  function readRebaseMetadataFile(fileName, continueOnError) {
    return fse.readFile(
      path.join(repository.path(), "rebase-merge", fileName),
      { encoding: "utf8" }
    )
      .then(fp.trim)
      .catch(function(err) {
        if (continueOnError) {
          return null;
        }
        throw err;
      });
  }

  function calcHeadName(input) {
    return input.replace(/refs\/heads\/(.*)/, "$1");
  }

  function getPromise() {
    return rebase.next()
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        if (index.hasConflicts()) {
          throw index;
        }

        return rebase.commit(null, signature);
      })
      .then(function() {

        return performRebase(
          repository,
          rebase,
          signature,
          beforeNextFn,
          beforeFinishFn
        );
      })
      .catch(function(error) {
        if (error && error.errno === NodeGit.Error.CODE.ITEROVER) {
          const calcRewritten = fp.cond([
            [fp.isEmpty, fp.constant(null)],
            [fp.stubTrue, fp.flow([
              fp.split("\n"),
              fp.map(fp.split(" "))
            ])]
          ]);

          const beforeFinishFnPromise = !beforeFinishFn ?
            Promise.resolve() :
            Promise.all([
              readRebaseMetadataFile("onto_name"),
              readRebaseMetadataFile("onto"),
              readRebaseMetadataFile("head-name").then(calcHeadName),
              readRebaseMetadataFile("orig-head"),
              readRebaseMetadataFile("rewritten", true).then(calcRewritten)
            ])
              .then(function([
                ontoName,
                ontoSha,
                originalHeadName,
                originalHeadSha,
                rewritten
              ]) {
                return beforeFinishFn({
                  ontoName,
                  ontoSha,
                  originalHeadName,
                  originalHeadSha,
                  rebase,
                  rewritten
                });
              });

          return beforeFinishFnPromise
            .then(function() {
              return rebase.finish(signature);
            });
        } else {
          throw error;
        }
      });
  }

  if(beforeNextFn) {
    beforeNextFnResult = beforeNextFn(rebase);
    // if beforeNextFn returns a promise, chain the promise
    return Promise.resolve(beforeNextFnResult)
      .then(getPromise);
  }

  return getPromise();
}
function performRebase ( repository , rebase , signature , beforeNextFn , beforeFinishFn ) { var beforeNextFnResult ; /* In the case of FF merges and a beforeFinishFn, this will fail
   * when looking for 'rewritten' so we need to handle that case.
   */ function readRebaseMetadataFile ( fileName , continueOnError ) { return fse . readFile ( path . join ( repository . path ( ) , "rebase-merge" , fileName ) , { encoding : "utf8" } ) . then ( fp . trim ) . catch ( function ( err ) { if ( continueOnError ) { return null ; } throw err ; } ) ; } function calcHeadName ( input ) { return input . replace ( / refs\/heads\/(.*) / , "$1" ) ; } function getPromise ( ) { return rebase . next ( ) . then ( function ( ) { return repository . refreshIndex ( ) ; } ) . then ( function ( index ) { if ( index . hasConflicts ( ) ) { throw index ; } return rebase . commit ( null , signature ) ; } ) . then ( function ( ) { return performRebase ( repository , rebase , signature , beforeNextFn , beforeFinishFn ) ; } ) . catch ( function ( error ) { if ( error && error . errno === NodeGit . Error . CODE . ITEROVER ) { const calcRewritten = fp . cond ( [ [ fp . isEmpty , fp . constant ( null ) ] , [ fp . stubTrue , fp . flow ( [ fp . split ( "\n" ) , fp . map ( fp . split ( " " ) ) ] ) ] ] ) ; const beforeFinishFnPromise = ! beforeFinishFn ? Promise . resolve ( ) : Promise . all ( [ readRebaseMetadataFile ( "onto_name" ) , readRebaseMetadataFile ( "onto" ) , readRebaseMetadataFile ( "head-name" ) . then ( calcHeadName ) , readRebaseMetadataFile ( "orig-head" ) , readRebaseMetadataFile ( "rewritten" , true ) . then ( calcRewritten ) ] ) . then ( function ( [ ontoName , ontoSha , originalHeadName , originalHeadSha , rewritten ] ) { return beforeFinishFn ( { ontoName , ontoSha , originalHeadName , originalHeadSha , rebase , rewritten } ) ; } ) ; return beforeFinishFnPromise . then ( function ( ) { return rebase . finish ( signature ) ; } ) ; } else { throw error ; } } ) ; } if ( beforeNextFn ) { beforeNextFnResult = beforeNextFn ( rebase ) ; // if beforeNextFn returns a promise, chain the promise return Promise . resolve ( beforeNextFnResult ) . then ( getPromise ) ; } return getPromise ( ) ; }
Goes through a rebase's rebase operations and commits them if there are
no merge conflicts

@param {Repository}  repository    The repository that the rebase is being
performed in
@param {Rebase}      rebase        The current rebase being performed
@param {Signature}   signature     Identity of the one performing the rebase
@param {Function}    beforeNextFn  Callback to be called before each
invocation of next(). If the callback
returns a promise, the next() will be
called when the promise resolves.
@param {Function}   beforeFinishFn Callback called before the invocation
of finish(). If the callback returns a
promise, finish() will be called when the
promise resolves. This callback will be
provided a detailed overview of the rebase
@return {Int|Index} An error code for an unsuccesful rebase or an index for
a rebase with conflicts
Goes through a rebase s rebase operations and commits them if there are no merge conflicts