55
66#include < git2/remote.h>
77
8+ #include " ../subcommand/diff_subcommand.hpp"
89#include " ../subcommand/stash_subcommand.hpp"
910#include " ../subcommand/status_subcommand.hpp"
10- #include " ../wrapper/repository_wrapper.hpp"
1111
1212bool has_subcommand (CLI::App* cmd)
1313{
14- std::vector<std::string> subs = { " push" , " pop" , " list" , " apply" };
14+ std::vector<std::string> subs = { " push" , " pop" , " list" , " apply" , " show " };
1515 return std::any_of (subs.begin (), subs.end (), [cmd](const std::string& s) { return cmd->got_subcommand (s); });
1616}
1717
@@ -22,10 +22,15 @@ stash_subcommand::stash_subcommand(const libgit2_object&, CLI::App& app)
2222 auto * list = stash->add_subcommand (" list" , " " );
2323 auto * pop = stash->add_subcommand (" pop" , " " );
2424 auto * apply = stash->add_subcommand (" apply" , " " );
25+ auto * show = stash->add_subcommand (" show" , " Show the changes recorded in the stash as a diff" );
2526
2627 push->add_option (" -m,--message" , m_message, " " );
2728 pop->add_option (" --index" , m_index, " " );
2829 apply->add_option (" --index" , m_index, " " );
30+ show->add_flag (" --stat" , m_stat_flag, " Generate a diffstat" );
31+ show->add_flag (" --shortstat" , m_shortstat_flag, " Output only the last line of --stat" );
32+ show->add_flag (" --numstat" , m_numstat_flag, " Machine-friendly --stat" );
33+ show->add_flag (" --summary" , m_summary_flag, " Output a condensed summary" );
2934
3035 stash->callback ([this ,stash]()
3136 {
@@ -38,6 +43,7 @@ stash_subcommand::stash_subcommand(const libgit2_object&, CLI::App& app)
3843 list->callback ([this ]() { this ->run_list (); });
3944 pop->callback ([this ]() { this ->run_pop (); });
4045 apply->callback ([this ]() { this ->run_apply (); });
46+ show->callback ([this ]() { this ->run_show (); });
4147}
4248
4349void stash_subcommand::run_push ()
@@ -66,14 +72,20 @@ void stash_subcommand::run_list()
6672 throw_if_error (git_stash_foreach (repo, list_stash_cb, NULL ));
6773}
6874
75+ git_oid stash_subcommand::resolve_stash_commit (repository_wrapper& repo)
76+ {
77+ std::string stash_spec = " stash@{" + std::to_string (m_index) + " }" ;
78+ auto stash_obj = repo.revparse_single (stash_spec);
79+ git_oid stash_id = stash_obj->oid ();
80+ return stash_id;
81+ }
82+
6983void stash_subcommand::run_pop ()
7084{
7185 auto directory = get_current_git_path ();
7286 auto repo = repository_wrapper::open (directory);
7387
74- std::string stash_spec = " stash@{" + std::to_string (m_index) + " }" ;
75- auto stash_obj = repo.revparse_single (stash_spec);
76- git_oid stash_id = stash_obj->oid ();
88+ git_oid stash_id = resolve_stash_commit (repo);
7789 char id_string[GIT_OID_HEXSZ + 1 ];
7890 git_oid_tostr (id_string, sizeof (id_string), &stash_id);
7991
@@ -90,3 +102,33 @@ void stash_subcommand::run_apply()
90102 throw_if_error (git_stash_apply (repo, m_index, NULL ));
91103 status_run ();
92104}
105+
106+ void stash_subcommand::run_show ()
107+ {
108+ auto directory = get_current_git_path ();
109+ auto repo = repository_wrapper::open (directory);
110+
111+ git_oid stash_id = resolve_stash_commit (repo);
112+ commit_wrapper stash_commit = repo.find_commit (stash_id);
113+
114+ if (git_commit_parentcount (stash_commit) < 1 )
115+ {
116+ throw std::runtime_error (" stash show: stash commit has no parents" );
117+ }
118+
119+ commit_wrapper parent_commit = stash_commit.get_parent (0 );
120+
121+ tree_wrapper stash_tree = stash_commit.tree ();
122+ tree_wrapper parent_tree = parent_commit.tree ();
123+
124+ git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
125+
126+ diff_wrapper diff = repo.diff_tree_to_tree (parent_tree, stash_tree, &diff_opts);
127+
128+ bool use_colour = true ;
129+ if (!m_shortstat_flag && !m_numstat_flag && !m_summary_flag)
130+ {
131+ m_stat_flag = true ;
132+ }
133+ print_stats (diff, use_colour, m_stat_flag, m_shortstat_flag, m_numstat_flag, m_summary_flag);
134+ }
0 commit comments