You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: line_strategy.rb
    path of file: ./repos/gitlabhq/lib/gitlab/diff/position_tracer
    
    the code of the file until where you have to start completion: # frozen_string_literal: true

module Gitlab
  module Diff
    class PositionTracer
      class LineStrategy < BaseStrategy
        def trace(position)
          # Suppose we have an MR with source branch `feature` and target branch `master`.
          # When the MR was created, the head of `master` was commit A, and the
          # head of `feature` was commit B, resulting in the original diff A->B.
          # Since creation, `master` was updated to C.
          # Now `feature` is being updated to D, and the newly generated MR diff is C->D.
          # It is possible that C and D are direct descendants of A and B respectively,
          # but this isn't necessarily the case as rebases and merges come into play.
          #
          # Suppose we have a diff note on the original diff A->B. Now that the MR
          # is updated, we need to find out what line in C->D corresponds to the
          # line the note was originally created on, so that we can update the diff note's
          # records and continue to display it in the right place in the diffs.
          # If we cannot find this line in the new diff, this means the diff note is now
          # outdated, and we will display that fact to the user.
          #
          # In the new diff, the file the diff note was originally created on may
          # have been renamed, deleted or even created, if the file existed in A and B,
          # but was removed in C, and restored in D.
          #
          # Every diff note stores a Position object that defines a specific location,
          # identified by paths and line numbers, within a specific diff, identified
          # by start, head and base commit ids.
          #
          # For diff notes for diff A->B, the position looks like this:
          # Position
          #   start_sha - ID of commit A
          #   head_sha - ID of commit B
          #   base_sha - ID of base commit of A and B
          #   old_path - path as of A (nil if file was newly created)
          #   new_path - path as of B (nil if file was deleted)
          #   old_line - line number as of A (nil if file was newly created)
          #   new_line - line number as of B (nil if file was deleted)
          #
          # We can easily update `start_sha` and `head_sha` to hold the IDs of
          # commits C and D, and can trivially determine `base_sha` based on those,
          # but need to find the paths and line numbers as of C and D.
          #
          # If the file was unchanged or newly created in A->B, the path as of D can be found
          # by generating diff B->D ("head to head"), finding the diff file with
          # `diff_file.old_path == position.new_path`, and taking `diff_file.new_path`.
          # The path as of C can be found by taking diff C->D, finding the diff file
          # with that same `new_path` and taking `diff_file.old_path`.
          # The line number as of D can be found by using the LineMapper on diff B->D
          # and providing the line number as of B.
          # T
    
        def trace(position)
          # Suppose we have an MR with source branch `feature` and target branch `master`.
          # When the MR was created, the head of `master` was commit A, and the
          # head of `feature` was commit B, resulting in the original diff A->B.
          # Since creation, `master` was updated to C.
          # Now `feature` is being updated to D, and the newly generated MR diff is C->D.
          # It is possible that C and D are direct descendants of A and B respectively,
          # but this isn't necessarily the case as rebases and merges come into play.
          #
          # Suppose we have a diff note on the original diff A->B. Now that the MR
          # is updated, we need to find out what line in C->D corresponds to the
          # line the note was originally created on, so that we can update the diff note's
          # records and continue to display it in the right place in the diffs.
          # If we cannot find this line in the new diff, this means the diff note is now
          # outdated, and we will display that fact to the user.
          #
          # In the new diff, the file the diff note was originally created on may
          # have been renamed, deleted or even created, if the file existed in A and B,
          # but was removed in C, and restored in D.
          #
          # Every diff note stores a Position object that defines a specific location,
          # identified by paths and line numbers, within a specific diff, identified
          # by start, head and base commit ids.
          #
          # For diff notes for diff A->B, the position looks like this:
          # Position
          #   start_sha - ID of commit A
          #   head_sha - ID of commit B
          #   base_sha - ID of base commit of A and B
          #   old_path - path as of A (nil if file was newly created)
          #   new_path - path as of B (nil if file was deleted)
          #   old_line - line number as of A (nil if file was newly created)
          #   new_line - line number as of B (nil if file was deleted)
          #
          # We can easily update `start_sha` and `head_sha` to hold the IDs of
          # commits C and D, and can trivially determine `base_sha` based on those,
          # but need to find the paths and line numbers as of C and D.
          #
          # If the file was unchanged or newly created in A->B, the path as of D can be found
          # by generating diff B->D ("head to head"), finding the diff file with
          # `diff_file.old_path == position.new_path`, and taking `diff_file.new_path`.
          # The path as of C can be found by taking diff C->D, finding the diff file
          # with that same `new_path` and taking `diff_file.old_path`.
          # The line number as of D can be found by using the LineMapper on diff B->D
          # and providing the line number as of B.
          # The line number as of C can be found by using the LineMapper on diff C->D
          # and providing the line number as of D.
          #
          # If the file was deleted in A->B, the path as of C can be found
          # by generating diff A->C ("base to base"), finding the diff file with
          # `diff_file.old_path == position.old_path`, and taking `diff_file.new_path`.
          # The path as of D can be found by taking diff C->D, finding the diff file
          # with `old_path` set to that `diff_file.new_path` and taking `diff_file.new_path`.
          # The line number as of C can be found by using the LineMapper on diff A->C
          # and providing the line number as of A.
          # The line number as of D can be found by using the LineMapper on diff C->D
          # and providing the line number as of C.

          @ignore_whitespace_change = position.ignore_whitespace_change

          if position.added?
            trace_added_line(position)
          elsif position.removed?
            trace_removed_line(position)
          else # unchanged
            trace_unchanged_line(position)
          end