Ejemplo n.º 1
0
 dest.saveAs(type, value, function (err) {
   if (err) return callback(err);
   if (type !== "tree") return callback();
   carallel(Object.keys(value).map(function (name) {
     return deepCopy(source, dest, value[name]);
   }), callback);
 }, entry.hash);
Ejemplo n.º 2
0
    function applyOverlays(tree, overlays, callback) {
      var local = {};
      var newTree = {};
      // Find local rules.
      Object.keys(tree).forEach(function (key) {
        var entry = tree[key];

        // Copy non-rules as-is
        if (entry.mode !== modes.exec || !/\.rule$/.test(key)) {
          newTree[key] = entry;
          return;
        }

        var childPath = path ? path + "/" + key : key;
        var childRule = {
          path: childPath,
          root: root,
          hash: entry.hash
        };
        key = key.substring(0, key.length - 5);
        local[key] = loadRule(childPath, childRule);
      });

      // Execute and merge in local rules
      carallel(local, function (err, results) {
        if (err) return callback(err);
        Object.keys(results).forEach(function (key) {
          if (!newTree[key]) {
            var entry = results[key];
            newTree[key] = entry;
          }
        });
        next();
      });

      // Execute overlays in order, deepest first.
      function next() {
        var overlay;
        do {
          overlay = overlays.pop();
          if (!overlay) {
            return callback(null, newTree);
          }
        } while (overlay.mode !== modes.tree);
        overlay.fetch(onTree);
      }

      function onTree(err, extra) {
        if (err) return callback(err);
        Object.keys(extra).forEach(function (key) {
          if (!newTree[key]) {
            newTree[key] = extra[key];
          }
        });
        next();
      }
    }
Ejemplo n.º 3
0
    function loadOverlays(overlays, callback) {
      carallel(rules.map(function (rule) {
        return loadRule(path, rule);
      }), function (err, entries) {
        if (err) return callback(err);

        entries.forEach(function (entry, i) {
          if (!entry) return;
          entry.rule = rules[i];
          overlays.push(entry);
        });
        callback();
      });
    }
Ejemplo n.º 4
0
  function moveEntry(path, target, callback) {
    if (!callback) return moveEntry.bind(null, path, target);
    var entry = resolvePath(path);
    if (!entry.hash) return callback(new Error("Can't find source"));

    copyConfig(path, target);
    carallel([
      writeEntry(path, {}),
      writeEntry(target, {
        mode: entry.mode,
        hash: entry.hash
      })
    ], callback);
    deleteConfig(path);
    platform.saveConfig();
  }
Ejemplo n.º 5
0
 function onProcessed(err, hashes) {
   if (err) return onWriteDone(err);
   for (var i = 0, l = leaves.length; i < l; i++) {
     var path = leaves[i];
     var hash = hashes[i];
     currents[path] = hash;
     if (!path) return onWriteDone();
     var parent = findParentPath(path, roots);
     var parentGroup = groups[parent] || (groups[parent] = {});
     var localPath = localbase(path, parent);
     parentGroup[localPath] = {
       mode: modes.commit,
       hash: hash
     };
   }
   leaves = findLeaves();
   if (!leaves.length) return onWriteDone();
   carallel(leaves.map(processLeaf), onProcessed);
 }
Ejemplo n.º 6
0
  // Given a bare config with { [url], [ref], [github], [head] },
  // create a live repo and look up the head commit hash.
  // => repo, current
  function livenConfig(config, current, callback) {
    var repo;
    try {
      repo = platform.createRepo(config);
      var ref = config.ref || (config.ref = "refs/heads/master");
    }
    catch (err) { return callback(err); }
    if (repo.initChain) return carallel(repo.initChain, onInit);
    else return onInit();

    function onInit(err) {
      if (err) return callback(err);
      if (repo.initChain) repo.initChain = null;
      if (config.head) onHead();
      else repo.readRef(ref, onHead);
    }

    function onHead(err, hash) {
      if (err) return callback(err);
      if (hash) config.head = hash;
      if (!current) {
        if (config.head) current = config.head;
        else if (config.url && !config.github) {
          return callback(new Error("TODO: Implement clone"));
        }
        else return initEmpty(repo, null, onCurrent);
      }
      config.current = current;
      callback(null, repo, current);
    }

    function onCurrent(err, hash) {
      if (!hash) return callback(err || new Error("Invalid current hash"));
      current = hash;
      onHead();
    }

    return repo;
  }
Ejemplo n.º 7
0
  function writeEntries() {
    // Exclusive write lock
    if (writing) return;
    writing = true;

    // Import write data into this closure
    // Other writes that happen while we're busy will get queued
    var writes = pendingWrites;
    pendingWrites = null;
    var callbacks = writeCallbacks;
    writeCallbacks = null;


    // If there are any changed .gitmodules we need to write those out as well.
    var changeNames = Object.keys(pendingChanges);
    if (changeNames.length) {
      changeNames.forEach(function (root) {
        var meta = pendingChanges[root].meta;
        var path = join(root, ".gitmodules");

        var encoded = codec.encode(meta);
        if (!encoded.trim()) {
          // Delete the file if it's now empty
          writes[path] = {};
        }
        else {
          writes[path] = {
            mode: modes.file,
            content: encoded
          };
        }
      });
      pendingChanges = {};
    }

    // Store output hashes by path
    var currents = {};

    // Break up the writes into the separate repos they belong in.
    var groups = {};
    var roots = Object.keys(configs);
    var paths = Object.keys(writes);
    for (var i = 0, l = paths.length; i < l; i++) {
      var path = paths[i];
      var entry = writes[path];
      if (!path) {
        currents[""] = entry.hash;
        return onWriteDone();
      }
      var root = findParentPath(path, roots);
      var group = groups[root] || (groups[root] = {});
      var local = localbase(path, root);
      group[local] = entry;
    }


    var leaves = findLeaves();

    if (!leaves.length) return onWriteDone();
    carallel(leaves.map(processLeaf), onProcessed);

    // Find repo groups that have no dependencies and process them in parallel
    function findLeaves() {
      var paths = Object.keys(groups);
      var parents = {};
      paths.forEach(function (path) {
        // we use an if to filter out the root path.  It doesn't have a parent.
        if (path) parents[findParentPath(path, paths)] = true;
      });

      return paths.filter(function (path) {
        return !parents[path];
      });
    }

    // Delegate most of the work out to repo.createTree
    // When it comes back, create a temporary commit.
    function processLeaf(root) {
      var config = configs[root];
      var repo = findRepo(root);
      var group = groups[root];
      delete groups[root];
      var actions = Object.keys(group).map(function (path) {
        var entry = group[path];
        entry.path = path;
        return entry;
      });
      actions.base = cache[config.current].tree;
      return function (callback) {
        var treeHash;
        repo.createTree(actions, onTree);

        function onTree(err, hash) {
          if (err) return callback(err);
          treeHash = hash;
          if (config.head) {
            return repo.loadAs("commit", config.head, onHead);
          }
          onHead();
        }

        function onHead(err, head) {
          if (err) return callback(err);
          // If the tree matches the one in HEAD, revert to head.
          if (head && head.tree === treeHash) return callback(null, config.head);
          // If not create a temporary commit.
          var commit = {
            tree: treeHash,
            author: {
              name: "AutoCommit",
              email: "*****@*****.**"
            },
            message: "Uncommitted changes in tedit"
          };
          if (config.head) commit.parent = config.head;
          repo.saveAs("commit", commit, callback);
        }
      };
    }

    function onProcessed(err, hashes) {
      if (err) return onWriteDone(err);
      for (var i = 0, l = leaves.length; i < l; i++) {
        var path = leaves[i];
        var hash = hashes[i];
        currents[path] = hash;
        if (!path) return onWriteDone();
        var parent = findParentPath(path, roots);
        var parentGroup = groups[parent] || (groups[parent] = {});
        var localPath = localbase(path, parent);
        parentGroup[localPath] = {
          mode: modes.commit,
          hash: hash
        };
      }
      leaves = findLeaves();
      if (!leaves.length) return onWriteDone();
      carallel(leaves.map(processLeaf), onProcessed);
    }

    function onWriteDone(err) {
      if (err) {
        return callbacks.forEach(function (callback) {
          callback(err);
        });
      }

      // Update the configs
      Object.keys(currents).forEach(function (root) {
        var hash = currents[root];
        configs[root].current = hash;
      });
      platform.saveConfig();

      // Tell the callbacks we're done.
      callbacks.forEach(function (callback) {
        callback(err);
      });

      // Update the tree root to point to the new version
      setRoot(currents[""]);

      writing = false;

      // Flush and pending reads that were waiting on us to finish writing
      flushReads();

      // If there are writes that were waiting on us, start them now.
      if (pendingWrites) writeEntries();
    }

  }