Skip to content

Commit 5418212

Browse files
committed
Merge branch 'jk/replace-edit-raw'
Teach "git replace --edit" mode a "--raw" option to allow editing the bare-metal representation data of objects. * jk/replace-edit-raw: replace: add a --raw mode for --edit
2 parents dcc1b38 + 2deda62 commit 5418212

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

Documentation/git-replace.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ OPTIONS
7373
newly created object. See linkgit:git-var[1] for details about
7474
how the editor will be chosen.
7575

76+
--raw::
77+
When editing, provide the raw object contents rather than
78+
pretty-printed ones. Currently this only affects trees, which
79+
will be shown in their binary form. This is harder to work with,
80+
but can help when repairing a tree that is so corrupted it
81+
cannot be pretty-printed. Note that you may need to configure
82+
your editor to cleanly read and write binary data.
83+
7684
-l <pattern>::
7785
--list <pattern>::
7886
List replace refs for objects that match the given pattern (or

builtin/replace.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,12 @@ static int replace_object(const char *object_ref, const char *replace_ref, int f
188188
}
189189

190190
/*
191-
* Write the contents of the object named by "sha1" to the file "filename",
192-
* pretty-printed for human editing based on its type.
191+
* Write the contents of the object named by "sha1" to the file "filename".
192+
* If "raw" is true, then the object's raw contents are printed according to
193+
* "type". Otherwise, we pretty-print the contents for human editing.
193194
*/
194-
static void export_object(const unsigned char *sha1, const char *filename)
195+
static void export_object(const unsigned char *sha1, enum object_type type,
196+
int raw, const char *filename)
195197
{
196198
struct child_process cmd = { NULL };
197199
int fd;
@@ -202,7 +204,10 @@ static void export_object(const unsigned char *sha1, const char *filename)
202204

203205
argv_array_push(&cmd.args, "--no-replace-objects");
204206
argv_array_push(&cmd.args, "cat-file");
205-
argv_array_push(&cmd.args, "-p");
207+
if (raw)
208+
argv_array_push(&cmd.args, typename(type));
209+
else
210+
argv_array_push(&cmd.args, "-p");
206211
argv_array_push(&cmd.args, sha1_to_hex(sha1));
207212
cmd.git_cmd = 1;
208213
cmd.out = fd;
@@ -217,15 +222,15 @@ static void export_object(const unsigned char *sha1, const char *filename)
217222
* The sha1 of the written object is returned via sha1.
218223
*/
219224
static void import_object(unsigned char *sha1, enum object_type type,
220-
const char *filename)
225+
int raw, const char *filename)
221226
{
222227
int fd;
223228

224229
fd = open(filename, O_RDONLY);
225230
if (fd < 0)
226231
die_errno("unable to open %s for reading", filename);
227232

228-
if (type == OBJ_TREE) {
233+
if (!raw && type == OBJ_TREE) {
229234
const char *argv[] = { "mktree", NULL };
230235
struct child_process cmd = { argv };
231236
struct strbuf result = STRBUF_INIT;
@@ -265,7 +270,7 @@ static void import_object(unsigned char *sha1, enum object_type type,
265270
*/
266271
}
267272

268-
static int edit_and_replace(const char *object_ref, int force)
273+
static int edit_and_replace(const char *object_ref, int force, int raw)
269274
{
270275
char *tmpfile = git_pathdup("REPLACE_EDITOBJ");
271276
enum object_type type;
@@ -281,10 +286,10 @@ static int edit_and_replace(const char *object_ref, int force)
281286

282287
check_ref_valid(old, prev, ref, sizeof(ref), force);
283288

284-
export_object(old, tmpfile);
289+
export_object(old, type, raw, tmpfile);
285290
if (launch_editor(tmpfile, NULL, NULL) < 0)
286291
die("editing object file failed");
287-
import_object(new, type, tmpfile);
292+
import_object(new, type, raw, tmpfile);
288293

289294
free(tmpfile);
290295

@@ -297,6 +302,7 @@ static int edit_and_replace(const char *object_ref, int force)
297302
int cmd_replace(int argc, const char **argv, const char *prefix)
298303
{
299304
int force = 0;
305+
int raw = 0;
300306
const char *format = NULL;
301307
enum {
302308
MODE_UNSPECIFIED = 0,
@@ -310,6 +316,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
310316
OPT_CMDMODE('d', "delete", &cmdmode, N_("delete replace refs"), MODE_DELETE),
311317
OPT_CMDMODE('e', "edit", &cmdmode, N_("edit existing object"), MODE_EDIT),
312318
OPT_BOOL('f', "force", &force, N_("replace the ref if it exists")),
319+
OPT_BOOL(0, "raw", &raw, N_("do not pretty-print contents for --edit")),
313320
OPT_STRING(0, "format", &format, N_("format"), N_("use this format")),
314321
OPT_END()
315322
};
@@ -329,6 +336,10 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
329336
usage_msg_opt("-f only makes sense when writing a replacement",
330337
git_replace_usage, options);
331338

339+
if (raw && cmdmode != MODE_EDIT)
340+
usage_msg_opt("--raw only makes sense with --edit",
341+
git_replace_usage, options);
342+
332343
switch (cmdmode) {
333344
case MODE_DELETE:
334345
if (argc < 1)
@@ -346,7 +357,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
346357
if (argc != 1)
347358
usage_msg_opt("-e needs exactly one argument",
348359
git_replace_usage, options);
349-
return edit_and_replace(argv[0], force);
360+
return edit_and_replace(argv[0], force, raw);
350361

351362
case MODE_LIST:
352363
if (argc > 1)

0 commit comments

Comments
 (0)