KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kigit_pcb_merge.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 (C) 2023 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
24#include "kigit_pcb_merge.h"
25
28#include <richio.h>
29
30#include <board.h>
31
33
34void KIGIT_PCB_MERGE::findSetDifferences( const BOARD_ITEM_SET& aAncestorSet, const BOARD_ITEM_SET& aOtherSet,
35 std::vector<BOARD_ITEM*>& aAdded, std::vector<BOARD_ITEM*>& aRemoved,
36 std::vector<BOARD_ITEM*>& aChanged )
37{
38 auto it1 = aAncestorSet.begin();
39 auto it2 = aOtherSet.begin();
40
41 while( it1 != aAncestorSet.end() && it2 != aOtherSet.end() )
42 {
43 BOARD_ITEM* item1 = *it1;
44 BOARD_ITEM* item2 = *it2;
45
46 if( item1->m_Uuid < item2->m_Uuid )
47 {
48 aRemoved.push_back( item1 );
49 ++it1;
50 }
51 else if( item1->m_Uuid > item2->m_Uuid )
52 {
53 aAdded.push_back( item2 );
54 ++it2;
55 }
56 else
57 {
58 if( !( *item1 == *item2 ) )
59 aChanged.push_back( item1 );
60
61 ++it1;
62 ++it2;
63 }
64 }
65}
66
67
69{
71
72 const auto ancestor_set = aAncestor->GetItemSet();
73 const auto other_set = aOther->GetItemSet();
74
75 findSetDifferences( ancestor_set, other_set, differences.m_added, differences.m_removed, differences.m_changed );
76
77 return differences;
78}
79
80
82{
83 auto repo = const_cast<git_repository*>( git_merge_driver_source_repo( m_mergeDriver ) );
84 const git_index_entry* ancestor = git_merge_driver_source_ancestor( m_mergeDriver );
85 const git_index_entry* ours = git_merge_driver_source_ours( m_mergeDriver );
86 const git_index_entry* theirs = git_merge_driver_source_theirs( m_mergeDriver );
87
88 // Read ancestor index entry into a buffer
89
90 git_blob* ancestor_blob;
91 git_blob* ours_blob;
92 git_blob* theirs_blob;
93
94 if( git_blob_lookup( &ancestor_blob, repo, &ancestor->id ) != 0 )
95 {
96 return GIT_ENOTFOUND;
97 }
98
99 if( git_blob_lookup( &ours_blob, repo, &ours->id ) != 0 )
100 {
101 git_blob_free( ancestor_blob );
102 return GIT_ENOTFOUND;
103 }
104
105 if( git_blob_lookup( &theirs_blob, repo, &theirs->id ) != 0 )
106 {
107 git_blob_free( ancestor_blob );
108 git_blob_free( ours_blob );
109 return GIT_ENOTFOUND;
110 }
111
112 // Get the raw data from the blobs
113 BLOB_READER ancestor_reader( ancestor_blob );
114 PCB_IO_KICAD_SEXPR_PARSER ancestor_parser( &ancestor_reader, nullptr, nullptr );
115 BLOB_READER ours_reader( ours_blob );
116 PCB_IO_KICAD_SEXPR_PARSER ours_parser( &ours_reader, nullptr, nullptr );
117 BLOB_READER theirs_reader( theirs_blob );
118 PCB_IO_KICAD_SEXPR_PARSER theirs_parser( &theirs_reader, nullptr, nullptr );
119
120 std::unique_ptr<BOARD> ancestor_board;
121 std::unique_ptr<BOARD> ours_board;
122 std::unique_ptr<BOARD> theirs_board;
123
124 try
125 {
126 ancestor_board.reset( static_cast<BOARD*>( ancestor_parser.Parse() ) );
127 ours_board.reset( static_cast<BOARD*>( ours_parser.Parse() ) );
128 theirs_board.reset( static_cast<BOARD*>( theirs_parser.Parse() ) );
129 }
130 catch(const IO_ERROR&)
131 {
132 git_blob_free( ancestor_blob );
133 git_blob_free( ours_blob );
134 git_blob_free( theirs_blob );
135 return GIT_EUSER;
136 }
137
138 git_blob_free( ancestor_blob );
139 git_blob_free( ours_blob );
140 git_blob_free( theirs_blob );
141
142 // Parse the differences between the ancestor and ours
143 KIGIT_PCB_MERGE_DIFFERENCES ancestor_ours_differences = compareBoards( ancestor_board.get(), ours_board.get() );
144 KIGIT_PCB_MERGE_DIFFERENCES ancestor_theirs_differences = compareBoards( ancestor_board.get(), theirs_board.get() );
145
146 // Find the items that we modified and they deleted
147 std::set_intersection( ancestor_ours_differences.m_changed.begin(), ancestor_ours_differences.m_changed.end(),
148 ancestor_theirs_differences.m_removed.begin(), ancestor_theirs_differences.m_removed.end(),
149 std::inserter( we_modified_they_deleted, we_modified_they_deleted.begin() ) );
150
151 // Find the items that they modified and we deleted
152 std::set_intersection( ancestor_theirs_differences.m_changed.begin(), ancestor_theirs_differences.m_changed.end(),
153 ancestor_ours_differences.m_removed.begin(), ancestor_ours_differences.m_removed.end(),
154 std::inserter( they_modified_we_deleted, they_modified_we_deleted.begin() ) );
155
156 // Find the items that both we and they modified
157 std::set_intersection( ancestor_ours_differences.m_changed.begin(), ancestor_ours_differences.m_changed.end(),
158 ancestor_theirs_differences.m_changed.begin(), ancestor_theirs_differences.m_changed.end(),
159 std::inserter( both_modified, both_modified.begin() ) );
160
161 return 0;
162}
163
164
165std::unique_ptr<BOARD> readBoard( wxString& aFilename )
166{
167 // Take input from stdin
168 FILE_LINE_READER reader( aFilename );
169
170 PCB_IO_KICAD_SEXPR_PARSER parser( &reader, nullptr, nullptr );
171 std::unique_ptr<BOARD> board;
172
173 try
174 {
175 board.reset( static_cast<BOARD*>( parser.Parse() ) );
176 }
177 catch( const IO_ERROR& )
178 {
179 }
180
181 return board;
182}
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
Definition: board.h:274
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:290
const BOARD_ITEM_SET GetItemSet()
Definition: board.cpp:3020
const KIID m_Uuid
Definition: eda_item.h:489
A LINE_READER that reads from an open file.
Definition: richio.h:185
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
std::set< BOARD_ITEM * > both_modified
void findSetDifferences(const BOARD_ITEM_SET &aAncestorSet, const BOARD_ITEM_SET &aOtherSet, std::vector< BOARD_ITEM * > &aAdded, std::vector< BOARD_ITEM * > &aRemoved, std::vector< BOARD_ITEM * > &aChanged)
git_merge_driver_source * m_mergeDriver
KIGIT_PCB_MERGE_DIFFERENCES compareBoards(BOARD *aAncestor, BOARD *aOther)
std::set< BOARD_ITEM * > they_modified_we_deleted
std::set< BOARD_ITEM * > we_modified_they_deleted
Read a Pcbnew s-expression formatted LINE_READER object and returns the appropriate BOARD_ITEM object...
std::unique_ptr< BOARD > readBoard(wxString &aFilename)
Pcbnew s-expression file format parser definition.
std::vector< BOARD_ITEM * > m_removed
std::vector< BOARD_ITEM * > m_changed
std::vector< BOARD_ITEM * > m_added