<commit_before>"use babel"

class Diff {
  constructor({gitIndex, filePath}) {
    this.gitIndex = gitIndex
    this.filePath = filePath
  }

  // Maps staged data onto a diff of the HEAD -> the working dir
  async getPatch () {
    await this.gitIndex.getStatuses()

    let all = this.gitIndex.getPatch(this.filePath, 'all')
    let staged = this.gitIndex.getPatch(this.filePath, 'staged')

    allPatch = await all
    stagedPatch = await staged

    let allHunks = await this._extractHunks(allPatch)
    let stagedHunks = await this._extractHunks(stagedPatch)

    // This is not really correct. Problematic when there are staged changes,
    // then another change is made in the area of the staged change.
    for(let hunk of allHunks) {
      for(let line of hunk.lines) {
        if(this._lineInHunks(line, stagedHunks)){
          console.log('STAGED', line.oldLineno(), line.newLineno(), line.content().split(/[\r\n]/g)[0])
          line.staged = true
        }
      }
    }

    return {
      entry: {
        path: this.filePath,
        status: 'all'
      },
      patch: new Patch(allPatch, allHunks)
    }
  }

  _lineInHunks(lineToFind, hunks) {
    for(let hunk of hunks) {
      for(let line of hunk.lines) {
        if(this._linesEqual(line, lineToFind))
          return true
      }
    }
  }

  _linesEqual(lineA, lineB) {
    let contentA = lineA.content().split(/[\r\n]/g)[0]
    let contentB = lineB.content().split(/[\r\n]/g)[0]

    return lineA.oldLineno() == lineB.oldLineno() &&
      lineA.newLineno() == lineB.newLineno() &&
      contentA == contentB
  }

  async _extractHunks(patch) {
    let hunks = []
    if (patch) {
      for (let hunk of (await patch.hunks())) {
        let lines = await hunk.lines()
        hunks.push(new Hunk(hunk.header(), lines))
      }
    }
    return hunks
  }
}

class Patch {
  constructor(patch, hunks) {
    this._patch = patch
    this.newPathName = patch.newFile().path()
    this.oldPathName = patch.oldFile().path()
    this.hunks = hunks
    for(let hunk of hunks) {
      hunk.patch = this
    }
  }

  getRaw() {
    return this._patch
  }

  size() {
    return this._patch.size()
  }

  isRenamed() {
    return this._patch.isRenamed()
  }

  isAdded() {
    return this._patch.isAdded()
  }

  isUntracked() {
    return this._patch.isUntracked()
  }

  isDeleted() {
    return this._patch.isDeleted()
  }
}

class Hunk {
  constructor(header, lines) {
    this.header = header
    this.lines = lines
  }
}

module.exports = Diff<commit_msg>Pass hunk around<commit_after>"use babel"

class Diff {
  constructor({gitIndex, filePath}) {
    this.gitIndex = gitIndex
    this.filePath = filePath
  }

  // Maps staged data onto a diff of the HEAD -> the working dir
  async getPatch () {
    await this.gitIndex.getStatuses()

    let all = this.gitIndex.getPatch(this.filePath, 'all')
    let staged = this.gitIndex.getPatch(this.filePath, 'staged')

    allPatch = await all
    stagedPatch = await staged

    let allHunks = await this._extractHunks(allPatch)
    let stagedHunks = await this._extractHunks(stagedPatch)

    // This is not really correct. Problematic when there are staged changes,
    // then another change is made in the area of the staged change.
    for(let hunk of allHunks) {
      for(let line of hunk.lines) {
        if(this._lineInHunks(line, stagedHunks)){
          console.log('STAGED', line.oldLineno(), line.newLineno(), line.content().split(/[\r\n]/g)[0])
          line.staged = true
        }
      }
    }

    return {
      entry: {
        path: this.filePath,
        status: 'all'
      },
      patch: new Patch(allPatch, allHunks)
    }
  }

  _lineInHunks(lineToFind, hunks) {
    for(let hunk of hunks) {
      for(let line of hunk.lines) {
        if(this._linesEqual(line, lineToFind))
          return true
      }
    }
  }

  _linesEqual(lineA, lineB) {
    let contentA = lineA.content().split(/[\r\n]/g)[0]
    let contentB = lineB.content().split(/[\r\n]/g)[0]

    return lineA.oldLineno() == lineB.oldLineno() &&
      lineA.newLineno() == lineB.newLineno() &&
      contentA == contentB
  }

  async _extractHunks(patch) {
    let hunks = []
    if (patch) {
      for (let hunk of (await patch.hunks())) {
        let lines = await hunk.lines()
        hunks.push(new Hunk(hunk, lines))
      }
    }
    return hunks
  }
}

class Patch {
  constructor(patch, hunks) {
    this._patch = patch
    this.newPathName = patch.newFile().path()
    this.oldPathName = patch.oldFile().path()
    this.hunks = hunks
    for(let hunk of hunks) {
      hunk.patch = this
    }
  }

  getRaw() {
    return this._patch
  }

  size() {
    return this._patch.size()
  }

  isRenamed() {
    return this._patch.isRenamed()
  }

  isAdded() {
    return this._patch.isAdded()
  }

  isUntracked() {
    return this._patch.isUntracked()
  }

  isDeleted() {
    return this._patch.isDeleted()
  }
}

class Hunk {
  constructor(hunk, lines) {
    this._hunk = hunk
    this.header = hunk.header()
    this.lines = lines
  }
}

module.exports = Diff
{'fraction_non_alphanumeric': 0.12999803033287374, 'fraction_numerical': 0.0011818002757533978, 'mean_word_length': 2.4149293880295897, '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': '6231360', 'n_tokens_mistral': 1842, 'n_tokens_neox': 1751, 'n_words': 389}