# Code coverage report for lib/git/repo.js

## Statements: 100% (66 / 66) Branches: 100% (28 / 28) Functions: 100% (7 / 7) Lines: 100% (62 / 62) Ignored: none

All files » lib/git/ » repo.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    1281
    1
    1
    1
    1

    1

    1

    1

    1

    1

    1
    55

    55

    54
    4

    50

    47
    1

    46
    46
    1

    45
    45
    45
    45
    45
    45

    45

    47

    1
    5

    1
    47
    47

    47

    47

    47

    47
    71

    71
    71

    47
    49
    49

    49
    49

    47

    47
    45

    45

    14

    14
    22
    22
    22
    20
    1

    19
    13

    8

    47

    1
     var _ = require('underscore');
    var fs = require('fs');
    var path = require('path');
    var mkdirp = require('mkdirp');
    var util = require('util');

    var logger = require('../logging.js');

    var git = require('./');

    var Branch = require('./branch.js');

    var utils = require('../utils.js');

    var hook_providers = {
      'bitbucket' : require('./hooks/webhook.js').bitbucket,
      'github' : require('./hooks/webhook.js').github,
      'stash' : require('./hooks/webhook.js').stash,
      'polling' : require('./hooks/polling.js')
    };

    /**
     * Create a new repo.  This will perform a number of validations, throwing an exception if any fail.
     * It will also set up the internal state of the object, including a Branch object for every branch
     * in the repo, but initialization of the branches and repos is deferred to the init method.
     */
    function Repo(repo_config) {
      var this_obj = this;

      if (!repo_config) throw new Error('No configuration provided for repo');

      if (!repo_config.local_store || !repo_config.url || !repo_config.name || !repo_config.branches) {
        throw new Error("A repo must have a local_store, a url, a name, and a branch array.");
      }

      // Check to make sure local_store is valid and writeable.
      utils.validate_writeable_directory(repo_config.local_store);

      if (repo_config.branches.length === 0) {
        throw new Error('No branches specified.');
      }

      var unique_branches = _.uniq(repo_config.branches);
      if (unique_branches.length !== repo_config.branches.length) {
        throw new Error("Duplicate name found in branches for repo " + repo_config.name + ": " + repo_config.branches);
      }

      var branches = {};
      Object.defineProperty(this, 'name', {value: repo_config.name});
      Object.defineProperty(this, 'url', {value: repo_config.url});
      Object.defineProperty(this, 'branch_names', {value: repo_config.branches});
      Object.defineProperty(this, 'branches', {value: branches});
      Object.defineProperty(this, 'hooks', {value: repo_config.hooks});

      repo_config.branches.forEach(function(branch) {
        // TODO: Switch to passing in the repo, not the repo_config.
        branches[branch] = new Branch(repo_config, branch);
      });
    }

    Repo.prototype.getBranch = function(branch_name) {
      return this.branches[branch_name];
    };

    Repo.prototype.init = function(cb) {
      var this_obj = this;
      var branch_count = 0;

      logger.info("Initting repo %s", this.name);

      var pending_operations = 0;

      var errs = [];

      var wrapped_cb = function(err) {
        if (err) errs.push(err);

        --pending_operations;
        if (pending_operations === 0) return cb(errs.length > 0 ? errs : undefined);
      };

      for (var branch_name in this.branches) {
        ++pending_operations;
        var branch = this.branches[branch_name];

        branch.init(function(err) {
          if (err) return wrapped_cb(err);

          ++branch_count;

          // Validate that we are tracking each Branch before enabling hooks to avoid any
          // race conditions where a hook fires before a Branch is initialized.
          if (branch_count === this_obj.branch_names.length) {
            logger.debug('Branches initialized');

            if (git.daemon && this_obj.hooks) {

              // Flag that hooks are running.  This data can be used by unit tests to validate
              // that daemon config is working properly.
              Object.defineProperty(this_obj, 'hooks_active', {value: true});

              // Init hooks
              this_obj.hooks.forEach(function(hook) {
                ++pending_operations;
                try {
                  var hook_provider = hook_providers[hook.type];
                  if (!hook_provider) {
                    return wrapped_cb("Invalid hook type " + hook.type);
                  }

                  hook_provider.init(hook, this_obj);
                  wrapped_cb();
                } catch (e) {
                  return wrapped_cb("Hook configuration failed due to " + e);
                }
              });

            }
          }

          wrapped_cb();
        });
      }

    };

    module.exports = Repo;