<commit_before>FBL.ns(function() { with (FBL) {
FireDiff.Path = {};

FireDiff.Path.updateForInsert = function(pathUpdate, pathInsert) {
  return this.updateForMutate(pathUpdate, pathInsert, 1, false);
};
FireDiff.Path.updateForRemove = function(pathUpdate, pathRemoved) {
  return this.updateForMutate(pathUpdate, pathRemoved, -1, true);
};

FireDiff.Path.updateForMutate = function(pathUpdate, pathChanged, offset, destroyAncestor) {
  var components = this.getRelativeComponents(pathUpdate, pathChanged);
  var changeParent = this.getParentPath(pathChanged);
  
  if (destroyAncestor && components.common == pathChanged) {
    // Path to update is the same or child of the one being removed
    return undefined;
  } else if (components.common == pathChanged) {
    // Parent or identity case
    return components.common.replace(
            /([^\/]+?)\[(\d+)\]$/,
            function(total, tag, index) {
              return tag + "[" + (parseInt(index)+offset) + "]";
            })
        + (components.left ? "/" : "")
        + components.left;
  } else if (components.left && components.common == changeParent) {
    // The removed path was the child of the common path element.
    // If the modified element was of the same type as our ancestor
    // at this level, then we will need to update our path
    var pathExtract = /^([^\/]+?)\[(\d+)\]/;
    var ancestor = pathExtract.exec(components.left);
    var changed = pathExtract.exec(components.right);

    if (ancestor[1] == changed[1]
        && parseInt(ancestor[2]) > parseInt(changed[2])) {
      return components.common
          + (components.common != "/" ? "/" : "")
          + components.left.replace(
              pathExtract,
              function(total, tag, index) {
                return tag + "[" + (parseInt(index)+offset) + "]";
              })
    }
  }
  
  // No effect on the path
  return pathUpdate;
};

FireDiff.Path.getIdentifier = function(path) {
  var match = path.match(/^.*\/(.+?)(?:\[(\d+)\])?$/);
  if (match) {
    return { tag: match[1], index: parseInt(match[2]) };
  }
};
FireDiff.Path.getParentPath = function(path) {
  return (path.match(/^(.+)\/.*?$/) || ["", "/"])[1];
};

FireDiff.Path.isChildOrSelf = function(parent, child) {
  return parent == child || this.isChild(parent, child);
};
FireDiff.Path.isChild = function(parent, child) {
  return child.indexOf(parent + "/") === 0;
};

FireDiff.Path.getRelativeComponents = function(path1, path2) {<commit_msg>Fix UT failure<commit_after>FBL.ns(function() { with (FBL) {
FireDiff.Path = {};

FireDiff.Path.updateForInsert = function(pathUpdate, pathInsert) {
  return this.updateForMutate(pathUpdate, pathInsert, 1, false);
};
FireDiff.Path.updateForRemove = function(pathUpdate, pathRemoved) {
  return this.updateForMutate(pathUpdate, pathRemoved, -1, true);
};

FireDiff.Path.updateForMutate = function(pathUpdate, pathChanged, offset, destroyAncestor) {
  var components = this.getRelativeComponents(pathUpdate, pathChanged);
  var changeParent = this.getParentPath(pathChanged);
  
  if (destroyAncestor && components.common == pathChanged) {
    // Path to update is the same or child of the one being removed
    return undefined;
  } else if (components.common == pathChanged) {
    // Parent or identity case
    return components.common.replace(
            /([^\/]+?)\[(\d+)\]$/,
            function(total, tag, index) {
              return tag + "[" + (parseInt(index)+offset) + "]";
            })
        + (components.left ? "/" : "")
        + components.left;
  } else if (components.left && components.common == changeParent) {
    // The removed path was the child of the common path element.
    // If the modified element was of the same type as our ancestor
    // at this level, then we will need to update our path
    var pathExtract = /^([^\/]+?)\[(\d+)\]/;
    var ancestor = pathExtract.exec(components.left);
    var changed = pathExtract.exec(components.right);

    if (ancestor[1] == changed[1]
        && parseInt(ancestor[2]) > parseInt(changed[2])) {
      return components.common
          + (components.common != "/" ? "/" : "")
          + components.left.replace(
              pathExtract,
              function(total, tag, index) {
                return tag + "[" + (parseInt(index)+offset) + "]";
              })
    }
  }
  
  // No effect on the path
  return pathUpdate;
};

FireDiff.Path.getIdentifier = function(path) {
  var match = path.match(/^.*\/(.+?)(?:\[(\d+)\])?$/);
  if (match) {
    return { tag: match[1], index: (match[2] || match[2] === "0") ? parseInt(match[2]) : undefined };
  }
};
FireDiff.Path.getParentPath = function(path) {
  return (path.match(/^(.+)\/.*?$/) || ["", "/"])[1];
};

FireDiff.Path.isChildOrSelf = function(parent, child) {
  return parent == child || this.isChild(parent, child);
};
FireDiff.Path.isChild = function(parent, child) {
  return child.indexOf(parent + "/") === 0;
};

FireDiff.Path.getRelativeComponents = function(path1, path2) {
{'fraction_non_alphanumeric': 0.1674, 'fraction_numerical': 0.0054, 'mean_word_length': 3.0493927125506075, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3708935', 'n_tokens_mistral': 1551, 'n_tokens_neox': 1541, 'n_words': 356}