@@ -2519,3 +2519,125 @@ int transform_todo_ids(int shorten_ids)
25192519 todo_list_release (& todo_list );
25202520 return 0 ;
25212521}
2522+
2523+ enum check_level {
2524+ CHECK_IGNORE = 0 , CHECK_WARN , CHECK_ERROR
2525+ };
2526+
2527+ static enum check_level get_missing_commit_check_level (void )
2528+ {
2529+ const char * value ;
2530+
2531+ if (git_config_get_value ("rebase.missingcommitscheck" , & value ) ||
2532+ !strcasecmp ("ignore" , value ))
2533+ return CHECK_IGNORE ;
2534+ if (!strcasecmp ("warn" , value ))
2535+ return CHECK_WARN ;
2536+ if (!strcasecmp ("error" , value ))
2537+ return CHECK_ERROR ;
2538+ warning (_ ("unrecognized setting %s for option"
2539+ "rebase.missingCommitsCheck. Ignoring." ), value );
2540+ return CHECK_IGNORE ;
2541+ }
2542+
2543+ /*
2544+ * Check if the user dropped some commits by mistake
2545+ * Behaviour determined by rebase.missingCommitsCheck.
2546+ * Check if there is an unrecognized command or a
2547+ * bad SHA-1 in a command.
2548+ */
2549+ int check_todo_list (void )
2550+ {
2551+ enum check_level check_level = get_missing_commit_check_level ();
2552+ struct strbuf todo_file = STRBUF_INIT ;
2553+ struct todo_list todo_list = TODO_LIST_INIT ;
2554+ struct strbuf missing = STRBUF_INIT ;
2555+ int advise_to_edit_todo = 0 , res = 0 , fd , i ;
2556+
2557+ strbuf_addstr (& todo_file , rebase_path_todo ());
2558+ fd = open (todo_file .buf , O_RDONLY );
2559+ if (fd < 0 ) {
2560+ res = error_errno (_ ("could not open '%s'" ), todo_file .buf );
2561+ goto leave_check ;
2562+ }
2563+ if (strbuf_read (& todo_list .buf , fd , 0 ) < 0 ) {
2564+ close (fd );
2565+ res = error (_ ("could not read '%s'." ), todo_file .buf );
2566+ goto leave_check ;
2567+ }
2568+ close (fd );
2569+ advise_to_edit_todo = res =
2570+ parse_insn_buffer (todo_list .buf .buf , & todo_list );
2571+
2572+ if (res || check_level == CHECK_IGNORE )
2573+ goto leave_check ;
2574+
2575+ /* Mark the commits in git-rebase-todo as seen */
2576+ for (i = 0 ; i < todo_list .nr ; i ++ ) {
2577+ struct commit * commit = todo_list .items [i ].commit ;
2578+ if (commit )
2579+ commit -> util = (void * )1 ;
2580+ }
2581+
2582+ todo_list_release (& todo_list );
2583+ strbuf_addstr (& todo_file , ".backup" );
2584+ fd = open (todo_file .buf , O_RDONLY );
2585+ if (fd < 0 ) {
2586+ res = error_errno (_ ("could not open '%s'" ), todo_file .buf );
2587+ goto leave_check ;
2588+ }
2589+ if (strbuf_read (& todo_list .buf , fd , 0 ) < 0 ) {
2590+ close (fd );
2591+ res = error (_ ("could not read '%s'." ), todo_file .buf );
2592+ goto leave_check ;
2593+ }
2594+ close (fd );
2595+ strbuf_release (& todo_file );
2596+ res = !!parse_insn_buffer (todo_list .buf .buf , & todo_list );
2597+
2598+ /* Find commits in git-rebase-todo.backup yet unseen */
2599+ for (i = todo_list .nr - 1 ; i >= 0 ; i -- ) {
2600+ struct todo_item * item = todo_list .items + i ;
2601+ struct commit * commit = item -> commit ;
2602+ if (commit && !commit -> util ) {
2603+ strbuf_addf (& missing , " - %s %.*s\n" ,
2604+ short_commit_name (commit ),
2605+ item -> arg_len , item -> arg );
2606+ commit -> util = (void * )1 ;
2607+ }
2608+ }
2609+
2610+ /* Warn about missing commits */
2611+ if (!missing .len )
2612+ goto leave_check ;
2613+
2614+ if (check_level == CHECK_ERROR )
2615+ advise_to_edit_todo = res = 1 ;
2616+
2617+ fprintf (stderr ,
2618+ _ ("Warning: some commits may have been dropped accidentally.\n"
2619+ "Dropped commits (newer to older):\n" ));
2620+
2621+ /* Make the list user-friendly and display */
2622+ fputs (missing .buf , stderr );
2623+ strbuf_release (& missing );
2624+
2625+ fprintf (stderr , _ ("To avoid this message, use \"drop\" to "
2626+ "explicitly remove a commit.\n\n"
2627+ "Use 'git config rebase.missingCommitsCheck' to change "
2628+ "the level of warnings.\n"
2629+ "The possible behaviours are: ignore, warn, error.\n\n" ));
2630+
2631+ leave_check :
2632+ strbuf_release (& todo_file );
2633+ todo_list_release (& todo_list );
2634+
2635+ if (advise_to_edit_todo )
2636+ fprintf (stderr ,
2637+ _ ("You can fix this with 'git rebase --edit-todo' "
2638+ "and then run 'git rebase --continue'.\n"
2639+ "Or you can abort the rebase with 'git rebase"
2640+ " --abort'.\n" ));
2641+
2642+ return res ;
2643+ }
0 commit comments