33#include "builtin.h"
44#include "config.h"
55#include "gettext.h"
6+ #include "hex.h"
7+ #include "odb.h"
68#include "revision.h"
79#include "reachable.h"
810#include "wildmatch.h"
1719#define BUILTIN_REFLOG_LIST_USAGE \
1820 N_("git reflog list")
1921
20- #define BUILTIN_REFLOG_EXPIRE_USAGE \
21- N_("git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" \
22- " [--rewrite] [--updateref] [--stale-fix]\n" \
23- " [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...]")
22+ #define BUILTIN_REFLOG_EXISTS_USAGE \
23+ N_("git reflog exists <ref>")
24+
25+ #define BUILTIN_REFLOG_WRITE_USAGE \
26+ N_("git reflog write <ref> <old-oid> <new-oid> <message>")
2427
2528#define BUILTIN_REFLOG_DELETE_USAGE \
2629 N_("git reflog delete [--rewrite] [--updateref]\n" \
2730 " [--dry-run | -n] [--verbose] <ref>@{<specifier>}...")
2831
29- #define BUILTIN_REFLOG_EXISTS_USAGE \
30- N_("git reflog exists <ref>")
31-
3232#define BUILTIN_REFLOG_DROP_USAGE \
3333 N_("git reflog drop [--all [--single-worktree] | <refs>...]")
3434
35+ #define BUILTIN_REFLOG_EXPIRE_USAGE \
36+ N_("git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" \
37+ " [--rewrite] [--updateref] [--stale-fix]\n" \
38+ " [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...]")
39+
3540static const char * const reflog_show_usage [] = {
3641 BUILTIN_REFLOG_SHOW_USAGE ,
3742 NULL ,
@@ -42,33 +47,39 @@ static const char *const reflog_list_usage[] = {
4247 NULL ,
4348};
4449
45- static const char * const reflog_expire_usage [] = {
46- BUILTIN_REFLOG_EXPIRE_USAGE ,
47- NULL
50+ static const char * const reflog_exists_usage [] = {
51+ BUILTIN_REFLOG_EXISTS_USAGE ,
52+ NULL ,
53+ };
54+
55+ static const char * const reflog_write_usage [] = {
56+ BUILTIN_REFLOG_WRITE_USAGE ,
57+ NULL ,
4858};
4959
5060static const char * const reflog_delete_usage [] = {
5161 BUILTIN_REFLOG_DELETE_USAGE ,
5262 NULL
5363};
5464
55- static const char * const reflog_exists_usage [] = {
56- BUILTIN_REFLOG_EXISTS_USAGE ,
57- NULL ,
58- };
59-
6065static const char * const reflog_drop_usage [] = {
6166 BUILTIN_REFLOG_DROP_USAGE ,
6267 NULL ,
6368};
6469
70+ static const char * const reflog_expire_usage [] = {
71+ BUILTIN_REFLOG_EXPIRE_USAGE ,
72+ NULL
73+ };
74+
6575static const char * const reflog_usage [] = {
6676 BUILTIN_REFLOG_SHOW_USAGE ,
6777 BUILTIN_REFLOG_LIST_USAGE ,
68- BUILTIN_REFLOG_EXPIRE_USAGE ,
78+ BUILTIN_REFLOG_EXISTS_USAGE ,
79+ BUILTIN_REFLOG_WRITE_USAGE ,
6980 BUILTIN_REFLOG_DELETE_USAGE ,
7081 BUILTIN_REFLOG_DROP_USAGE ,
71- BUILTIN_REFLOG_EXISTS_USAGE ,
82+ BUILTIN_REFLOG_EXPIRE_USAGE ,
7283 NULL
7384};
7485
@@ -392,6 +403,59 @@ static int cmd_reflog_drop(int argc, const char **argv, const char *prefix,
392403 return ret ;
393404}
394405
406+ static int cmd_reflog_write (int argc , const char * * argv , const char * prefix ,
407+ struct repository * repo )
408+ {
409+ const struct option options [] = {
410+ OPT_END ()
411+ };
412+ struct object_id old_oid , new_oid ;
413+ struct strbuf err = STRBUF_INIT ;
414+ struct ref_transaction * tx ;
415+ const char * ref , * message ;
416+ int ret ;
417+
418+ argc = parse_options (argc , argv , prefix , options , reflog_write_usage , 0 );
419+ if (argc != 4 )
420+ usage_with_options (reflog_write_usage , options );
421+
422+ ref = argv [0 ];
423+ if (!is_root_ref (ref ) && check_refname_format (ref , 0 ))
424+ die (_ ("invalid reference name: %s" ), ref );
425+
426+ ret = get_oid_hex_algop (argv [1 ], & old_oid , repo -> hash_algo );
427+ if (ret )
428+ die (_ ("invalid old object ID: '%s'" ), argv [1 ]);
429+ if (!is_null_oid (& old_oid ) && !has_object (the_repository , & old_oid , 0 ))
430+ die (_ ("old object '%s' does not exist" ), argv [1 ]);
431+
432+ ret = get_oid_hex_algop (argv [2 ], & new_oid , repo -> hash_algo );
433+ if (ret )
434+ die (_ ("invalid new object ID: '%s'" ), argv [2 ]);
435+ if (!is_null_oid (& new_oid ) && !has_object (the_repository , & new_oid , 0 ))
436+ die (_ ("new object '%s' does not exist" ), argv [2 ]);
437+
438+ message = argv [3 ];
439+
440+ tx = ref_store_transaction_begin (get_main_ref_store (repo ), 0 , & err );
441+ if (!tx )
442+ die (_ ("cannot start transaction: %s" ), err .buf );
443+
444+ ret = ref_transaction_update_reflog (tx , ref , & new_oid , & old_oid ,
445+ git_committer_info (0 ),
446+ message , 0 , & err );
447+ if (ret )
448+ die (_ ("cannot queue reflog update: %s" ), err .buf );
449+
450+ ret = ref_transaction_commit (tx , & err );
451+ if (ret )
452+ die (_ ("cannot commit reflog update: %s" ), err .buf );
453+
454+ ref_transaction_free (tx );
455+ strbuf_release (& err );
456+ return 0 ;
457+ }
458+
395459/*
396460 * main "reflog"
397461 */
@@ -404,10 +468,11 @@ int cmd_reflog(int argc,
404468 struct option options [] = {
405469 OPT_SUBCOMMAND ("show" , & fn , cmd_reflog_show ),
406470 OPT_SUBCOMMAND ("list" , & fn , cmd_reflog_list ),
407- OPT_SUBCOMMAND ("expire" , & fn , cmd_reflog_expire ),
408- OPT_SUBCOMMAND ("delete" , & fn , cmd_reflog_delete ),
409471 OPT_SUBCOMMAND ("exists" , & fn , cmd_reflog_exists ),
472+ OPT_SUBCOMMAND ("write" , & fn , cmd_reflog_write ),
473+ OPT_SUBCOMMAND ("delete" , & fn , cmd_reflog_delete ),
410474 OPT_SUBCOMMAND ("drop" , & fn , cmd_reflog_drop ),
475+ OPT_SUBCOMMAND ("expire" , & fn , cmd_reflog_expire ),
411476 OPT_END ()
412477 };
413478
0 commit comments