KiCad PCB EDA Suite
Loading...
Searching...
No Matches
git_compare_handler.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/gpl-3.0.html
19 * or you may search the http://www.gnu.org website for the version 3 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
27
28#include <git2.h>
29
30#include <trace_helpers.h>
31
32#include <wx/log.h>
33
34
35namespace KIGIT
36{
37
39{
40 switch( aStatus )
41 {
42 case FILE_CHANGE_STATUS::UNCHANGED: return "unchanged";
43 case FILE_CHANGE_STATUS::ADDED: return "added";
44 case FILE_CHANGE_STATUS::REMOVED: return "removed";
45 case FILE_CHANGE_STATUS::MODIFIED: return "modified";
46 case FILE_CHANGE_STATUS::RENAMED: return "renamed";
47 case FILE_CHANGE_STATUS::COPIED: return "copied";
48 case FILE_CHANGE_STATUS::TYPECHANGE: return "typechange";
49 }
50
51 return "unknown";
52}
53
54
55namespace
56{
57
58FILE_CHANGE_STATUS deltaStatusToEnum( git_delta_t aDelta )
59{
60 switch( aDelta )
61 {
62 case GIT_DELTA_UNMODIFIED: return FILE_CHANGE_STATUS::UNCHANGED;
63 case GIT_DELTA_ADDED: return FILE_CHANGE_STATUS::ADDED;
64 case GIT_DELTA_DELETED: return FILE_CHANGE_STATUS::REMOVED;
65 case GIT_DELTA_MODIFIED: return FILE_CHANGE_STATUS::MODIFIED;
66 case GIT_DELTA_RENAMED: return FILE_CHANGE_STATUS::RENAMED;
67 case GIT_DELTA_COPIED: return FILE_CHANGE_STATUS::COPIED;
68 case GIT_DELTA_TYPECHANGE: return FILE_CHANGE_STATUS::TYPECHANGE;
69 default: return FILE_CHANGE_STATUS::MODIFIED;
70 }
71}
72
73} // namespace
74
75
76std::vector<CHANGED_FILE> CompareRefs( git_repository* aRepo,
77 const wxString& aBaseRef,
78 const wxString& aHeadRef )
79{
80 std::vector<CHANGED_FILE> result;
81
82 if( !aRepo )
83 return result;
84
85 GitTreePtr baseTree( ResolveRefToTree( aRepo, aBaseRef ) );
86 GitTreePtr headTree( ResolveRefToTree( aRepo, aHeadRef ) );
87
88 if( !baseTree || !headTree )
89 return result;
90
91 git_diff* diff = nullptr;
92 git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
93
94 if( git_diff_tree_to_tree( &diff, aRepo, baseTree.get(), headTree.get(), &opts ) != 0 )
95 {
96 wxLogTrace( traceGit, "git_diff_tree_to_tree failed: %s",
98 return result;
99 }
100
101 GitDiffPtr diffPtr( diff );
102
103 // Find renames so the UI can show "renamed from X" instead of (REMOVED+ADDED).
104 git_diff_find_options findOpts = GIT_DIFF_FIND_OPTIONS_INIT;
105 findOpts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES;
106 git_diff_find_similar( diff, &findOpts );
107
108 result.reserve( git_diff_num_deltas( diff ) );
109
110 CollectDiffDeltas( diff,
111 [&result]( const git_diff_delta& aDelta )
112 {
113 CHANGED_FILE entry;
114 entry.status = deltaStatusToEnum( aDelta.status );
115 entry.path = wxString::FromUTF8( aDelta.new_file.path
116 ? aDelta.new_file.path
117 : aDelta.old_file.path );
118
119 if( aDelta.status == GIT_DELTA_RENAMED || aDelta.status == GIT_DELTA_COPIED )
120 entry.oldPath = wxString::FromUTF8( aDelta.old_file.path );
121
122 result.push_back( std::move( entry ) );
123 } );
124
125 return result;
126}
127
128} // namespace KIGIT
static wxString GetLastGitError()
const wxChar *const traceGit
Flag to enable Git debugging output.
std::unique_ptr< git_tree, decltype([](git_tree *aTree) { git_tree_free(aTree); })> GitTreePtr
A unique pointer for git_tree objects with automatic cleanup.
std::vector< CHANGED_FILE > CompareRefs(git_repository *aRepo, const wxString &aBaseRef, const wxString &aHeadRef)
Compare two git refs (branch / tag / commit OID) within a repository and return the per-file change l...
git_tree * ResolveRefToTree(git_repository *aRepo, const wxString &aRef)
Resolve a string ref (branch name, short OID, full OID, tag) to its tree.
const char * FileChangeStatusToString(FILE_CHANGE_STATUS aStatus)
void CollectDiffDeltas(git_diff *aDiff, const std::function< void(const git_diff_delta &)> &aCallback)
Walk every delta in a computed diff, invoking aCallback once per delta.
std::unique_ptr< git_diff, decltype([](git_diff *aDiff) { git_diff_free(aDiff); })> GitDiffPtr
A unique pointer for git_diff objects with automatic cleanup.
FILE_CHANGE_STATUS status
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.