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
@@ -395,6 +406,59 @@ static int cmd_reflog_drop(int argc, const char **argv, const char *prefix,
395406 return ret ;
396407}
397408
409+ static int cmd_reflog_write (int argc , const char * * argv , const char * prefix ,
410+ struct repository * repo )
411+ {
412+ const struct option options [] = {
413+ OPT_END ()
414+ };
415+ struct object_id old_oid , new_oid ;
416+ struct strbuf err = STRBUF_INIT ;
417+ struct ref_transaction * tx ;
418+ const char * ref , * message ;
419+ int ret ;
420+
421+ argc = parse_options (argc , argv , prefix , options , reflog_write_usage , 0 );
422+ if (argc != 4 )
423+ usage_with_options (reflog_write_usage , options );
424+
425+ ref = argv [0 ];
426+ if (!is_root_ref (ref ) && check_refname_format (ref , 0 ))
427+ die (_ ("invalid reference name: %s" ), ref );
428+
429+ ret = get_oid_hex_algop (argv [1 ], & old_oid , repo -> hash_algo );
430+ if (ret )
431+ die (_ ("invalid old object ID: '%s'" ), argv [1 ]);
432+ if (!is_null_oid (& old_oid ) && !odb_has_object (repo -> objects , & old_oid , 0 ))
433+ die (_ ("old object '%s' does not exist" ), argv [1 ]);
434+
435+ ret = get_oid_hex_algop (argv [2 ], & new_oid , repo -> hash_algo );
436+ if (ret )
437+ die (_ ("invalid new object ID: '%s'" ), argv [2 ]);
438+ if (!is_null_oid (& new_oid ) && !odb_has_object (repo -> objects , & new_oid , 0 ))
439+ die (_ ("new object '%s' does not exist" ), argv [2 ]);
440+
441+ message = argv [3 ];
442+
443+ tx = ref_store_transaction_begin (get_main_ref_store (repo ), 0 , & err );
444+ if (!tx )
445+ die (_ ("cannot start transaction: %s" ), err .buf );
446+
447+ ret = ref_transaction_update_reflog (tx , ref , & new_oid , & old_oid ,
448+ git_committer_info (0 ),
449+ message , 0 , & err );
450+ if (ret )
451+ die (_ ("cannot queue reflog update: %s" ), err .buf );
452+
453+ ret = ref_transaction_commit (tx , & err );
454+ if (ret )
455+ die (_ ("cannot commit reflog update: %s" ), err .buf );
456+
457+ ref_transaction_free (tx );
458+ strbuf_release (& err );
459+ return 0 ;
460+ }
461+
398462/*
399463 * main "reflog"
400464 */
@@ -407,10 +471,11 @@ int cmd_reflog(int argc,
407471 struct option options [] = {
408472 OPT_SUBCOMMAND ("show" , & fn , cmd_reflog_show ),
409473 OPT_SUBCOMMAND ("list" , & fn , cmd_reflog_list ),
410- OPT_SUBCOMMAND ("expire" , & fn , cmd_reflog_expire ),
411- OPT_SUBCOMMAND ("delete" , & fn , cmd_reflog_delete ),
412474 OPT_SUBCOMMAND ("exists" , & fn , cmd_reflog_exists ),
475+ OPT_SUBCOMMAND ("write" , & fn , cmd_reflog_write ),
476+ OPT_SUBCOMMAND ("delete" , & fn , cmd_reflog_delete ),
413477 OPT_SUBCOMMAND ("drop" , & fn , cmd_reflog_drop ),
478+ OPT_SUBCOMMAND ("expire" , & fn , cmd_reflog_expire ),
414479 OPT_END ()
415480 };
416481
0 commit comments