14
14
#include "parse-options.h"
15
15
16
16
static const char * const git_replace_usage [] = {
17
+ "git replace [-f] <object> <replacement>" ,
17
18
"git replace -d <object>..." ,
18
19
"git replace -l [<pattern>]" ,
19
20
NULL
@@ -77,12 +78,46 @@ static int delete_replace_ref(const char *name, const char *ref,
77
78
return 0 ;
78
79
}
79
80
81
+ static int replace_object (const char * object_ref , const char * replace_ref ,
82
+ int force )
83
+ {
84
+ unsigned char object [20 ], prev [20 ], repl [20 ];
85
+ char ref [PATH_MAX ];
86
+ struct ref_lock * lock ;
87
+
88
+ if (get_sha1 (object_ref , object ))
89
+ die ("Failed to resolve '%s' as a valid ref." , object_ref );
90
+ if (get_sha1 (replace_ref , repl ))
91
+ die ("Failed to resolve '%s' as a valid ref." , replace_ref );
92
+
93
+ if (snprintf (ref , sizeof (ref ),
94
+ "refs/replace/%s" ,
95
+ sha1_to_hex (object )) > sizeof (ref ) - 1 )
96
+ die ("replace ref name too long: %.*s..." , 50 , ref );
97
+ if (check_ref_format (ref ))
98
+ die ("'%s' is not a valid ref name." , ref );
99
+
100
+ if (!resolve_ref (ref , prev , 1 , NULL ))
101
+ hashclr (prev );
102
+ else if (!force )
103
+ die ("replace ref '%s' already exists" , ref );
104
+
105
+ lock = lock_any_ref_for_update (ref , prev , 0 );
106
+ if (!lock )
107
+ die ("%s: cannot lock the ref" , ref );
108
+ if (write_ref_sha1 (lock , repl , NULL ) < 0 )
109
+ die ("%s: cannot update the ref" , ref );
110
+
111
+ return 0 ;
112
+ }
113
+
80
114
int cmd_replace (int argc , const char * * argv , const char * prefix )
81
115
{
82
- int list = 0 , delete = 0 ;
116
+ int list = 0 , delete = 0 , force = 0 ;
83
117
struct option options [] = {
84
118
OPT_BOOLEAN ('l' , NULL , & list , "list replace refs" ),
85
119
OPT_BOOLEAN ('d' , NULL , & delete , "delete replace refs" ),
120
+ OPT_BOOLEAN ('f' , NULL , & force , "replace the ref if it exists" ),
86
121
OPT_END ()
87
122
};
88
123
@@ -91,15 +126,28 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
91
126
if (list && delete )
92
127
usage_with_options (git_replace_usage , options );
93
128
129
+ if (force && (list || delete ))
130
+ usage_with_options (git_replace_usage , options );
131
+
132
+ /* Delete refs */
94
133
if (delete ) {
95
134
if (argc < 1 )
96
135
usage_with_options (git_replace_usage , options );
97
136
return for_each_replace_name (argv , delete_replace_ref );
98
137
}
99
138
139
+ /* Replace object */
140
+ if (!list && argc ) {
141
+ if (argc != 2 )
142
+ usage_with_options (git_replace_usage , options );
143
+ return replace_object (argv [0 ], argv [1 ], force );
144
+ }
145
+
100
146
/* List refs, even if "list" is not set */
101
147
if (argc > 1 )
102
148
usage_with_options (git_replace_usage , options );
149
+ if (force )
150
+ usage_with_options (git_replace_usage , options );
103
151
104
152
return list_replace_refs (argv [0 ]);
105
153
}
0 commit comments