Как "удалить" файл с 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
,