Как "удалить" файл с Objective-Git (libgit2)?

Я пишу приложение, которое позволяет выполнять основные операции git с использованием Objective-Git, но у меня возникают проблемы с выяснением, как "удалить" файл. Более конкретно, у меня есть файл с изменениями, которые ранее были добавлены в текущий GTIndex, и теперь я хочу отменить эти изменения (без потери текущего состояния файла на диске).

Вот грубая схема соответствующей логики, которой сейчас руководствуется моя программа при переключении "промежуточного" состояния файла:

- Fetch current GTIndex using GTRepository.indexWithError:
- Fetch GTIndexEntry for the file using GTIndex.entryWithPath:
- If the file has an index and GTIndexEntry.status == GTIndexEntryStatusUpdated:
    - Here's where I'm stuck

В соответствии с этим старым неотвеченным вопросом мне нужно найти информацию о файле в текущем заголовке. В таком случае, это логика, к которой я пришел:

- Fetch head's GTReference using GTRepository.headReferenceWithError:
- If the reference resolves to a GTCommit object:
    - Fetch the GTTree using GTCommit.tree
    - Fetch the file's GTTreeEntry using GTTree.entryWithPath:error:
    - Stuck again! Do I convert GTTreeEntry to GTIndexEntry somehow?

Любое руководство приветствуется! Я не боюсь сразу перейти в libgit2 (этот проект уже требовал этого один или два раза), но, поскольку я работаю в Swift, я бы хотел избежать этого, если смогу, и "unstaging" файла Кажется, что это такая стандартная процедура, что я решил, что не должен понимать, как классы Objective-Git связаны друг с другом.

2 ответа

Решение

Позволив этому сидеть немного дольше, я обнаружил, что на самом деле это намного проще, чем я это делал; вместо того, чтобы сравнивать дерево HEAD с активным индексом, вы можете просто использовать GTRepository.statusForFile:success:error: чтобы определить, является ли файл промежуточным, нетонированным и т. д., а затем добавить, удалить или добавить большой двоичный объект для файла на основе тот.

Оригинальный подход

(По случайности он содержит полезную информацию для других в будущем.)

Это оказалось проще, чем казалось на первый взгляд, главным образом потому, что переход между GTTreeEntry и GTIndexEntry не нужен. Вместо этого мне просто нужно было получить GTObject GTTreeEntry (который является большим двоичным объектом для файлов), а затем передать данные большого двоичного объекта в GTIndex.

Я закончил с потоком кода, который выглядит примерно так:

- Fetch head's GTReference using GTRepository.headReferenceWithError:
- If the reference resolves to a GTCommit =>
    - Fetch the GTIndexEntry using GTIndex.entryWithPath:
    - If we have an index entry =>
        - Fetch the GTTree using GTCommit.tree
        - Fetch the GTTreeEntry using GTTree.entryWithPath:error:
        - If GTTreeEntry.SHA == GTIndexEntry.OID.SHA =>
            - GTIndex.addFile:error:
            (using this approach, it's possible to end up with identical
             tree and index entries, which means the file is unstaged)
        - Else if GTTreeEntry.type == GTObjectTypeBlob =>
            - Fetch GTBlob using GTTreeEntry.GTObject:error:
            - Pass GTBlob.data to GTIndex.addData:withPath:error:
        - Else if no GTTreeEntry => GTIndex.removeFile:error:
    - Else add the file/directory to the GTIndex (since we have no index entry)
    - Write the changes to disk with GTIndex.write:

Пара замечаний в надежде, что они будут полезны для будущих поколений людей, которые бьют головой о в основном незарегистрированную шкуру Objective-Git:

  • GTIndexEntry.status бесполезен в этом сценарии; он ссылается на некоторые флаги, которые используются внутри libgit2 при создании индекса, но не помогают впоследствии определить статус файлов (я, честно говоря, не уверен, почему эти флаги вообще доступны Objective-Git)
  • Если вы хотите удалить / поместить все файлы в рабочем каталоге, вы можете заставить Objective-Git выполнить большую часть работы, используя GTDiff +diffIndexFromTree:inRepository:options:error:

Когда у вас есть запись дерева из коммита HEAD, вы можете извлечь из него данные, чтобы заполнить новую запись индекса. Вам не нужно заполнять все поля, но по крайней мере установить path, mode, а также id, Вы можете скопировать их прямо из дерева. Затем используйте объективно-мерзавец эквивалент git_index_add обновить индекс с новой записью.

Если файл не существует в дереве HEAD (потому что он не отслеживался ранее), то вы можете просто удалить его из индекса с помощью git_index_remove_bypath,

Другие вопросы по тегам