Merge branch 'scintilla-551'
[TortoiseGit.git] / src / Git / GitRevRefBrowser.cpp
blobf7561cf282fc72f556d03003f0d5f56c6255bdfe
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2009-2020, 2024 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "stdafx.h"
20 #include "gittype.h"
21 #include "Git.h"
22 #include "GitRevRefBrowser.h"
23 #include "StringUtils.h"
24 #include "GitMailmap.h"
26 GitRevRefBrowser::GitRevRefBrowser() : GitRev()
30 void GitRevRefBrowser::Clear()
32 GitRev::Clear();
33 m_Description.Empty();
34 m_UpstreamRef.Empty();
37 int GitRevRefBrowser::GetGitRevRefMap(MAP_REF_GITREVREFBROWSER& map, int mergefilter, CString& err, std::function<bool(const CString& refName)> filterCallback)
39 err.Empty();
40 MAP_STRING_STRING descriptions;
41 g_Git.GetBranchDescriptions(descriptions);
43 CString args;
44 switch (mergefilter)
46 case 1:
47 args = L" --merged HEAD";
48 break;
49 case 2:
50 args = L" --no-merged HEAD";
51 break;
54 CString cmd;
55 cmd.Format(L"git.exe for-each-ref%s --format=\"%%(refname)%%04 %%(objectname)%%04 %%(upstream)%%04 %%(subject)%%04 %%(authorname)%%04 %%(authoremail)%%04 %%(authordate:raw)%%04 %%(committername)%%04 %%(committeremail)%%04 %%(committerdate:raw)%%04%%(creator)%%04 %%(creatordate:raw)%%03\"", static_cast<LPCWSTR>(args));
56 CString allRefs;
57 if (g_Git.Run(cmd, &allRefs, &err, CP_UTF8))
58 return -1;
60 int linePos = 0;
61 CString singleRef;
62 CGitMailmap mailmap;
63 while (!(singleRef = allRefs.Tokenize(L"\03", linePos)).IsEmpty())
65 singleRef.TrimLeft(L"\r\n");
66 int valuePos = 0;
67 CString refName = singleRef.Tokenize(L"\04", valuePos);
69 if (refName.IsEmpty() || (filterCallback && !filterCallback(refName)))
70 continue;
72 GitRevRefBrowser ref;
73 ref.m_CommitHash = CGitHash::FromHexStrTry(singleRef.Tokenize(L"\04", valuePos).Trim()); if (valuePos < 0) continue;
74 ref.m_UpstreamRef = singleRef.Tokenize(L"\04", valuePos).Trim(); if (valuePos < 0) continue;
75 ref.m_Subject = singleRef.Tokenize(L"\04", valuePos).Trim(); if (valuePos < 0) continue;
76 ref.m_AuthorName = singleRef.Tokenize(L"\04", valuePos).Trim(); if (valuePos < 0) continue;
77 CString email = singleRef.Tokenize(L"\04", valuePos).Trim().Trim(L"<>"); if (valuePos < 0) continue;
78 CString date = singleRef.Tokenize(L"\04", valuePos).Trim();
79 ref.m_AuthorDate = _wtoll(date);
80 ref.m_CommitterName = singleRef.Tokenize(L"\04", valuePos).Trim(); if (valuePos < 0) continue;
81 CString committerEmail = singleRef.Tokenize(L"\04", valuePos).Trim().Trim(L"<>"); if (valuePos < 0) continue;
82 ref.m_CommitterDate = _wtoll(singleRef.Tokenize(L"\04", valuePos).Trim());
83 if (ref.m_AuthorName.IsEmpty())
85 ref.m_AuthorName = singleRef.Tokenize(L"\04", valuePos).Trim(); if (valuePos < 0) continue;
86 email = ref.m_AuthorName.Mid(ref.m_AuthorName.Find(L" <") + static_cast<int>(wcslen(L" <")));
87 email.Truncate(max(0, email.Find(L'>')));
88 ref.m_AuthorName.Truncate(max(0, ref.m_AuthorName.Find(L" <")));
89 date = singleRef.Tokenize(L"\04", valuePos).Trim();
90 ref.m_AuthorDate = _wtoll(date);
91 if (ref.m_CommitterName.IsEmpty())
93 ref.m_CommitterName = ref.m_AuthorName;
94 committerEmail = email;
95 ref.m_CommitterDate = ref.m_AuthorDate;
98 if (mailmap)
100 ref.m_AuthorName = mailmap.TranslateAuthor(ref.m_AuthorName, email);
101 ref.m_CommitterName = mailmap.TranslateAuthor(ref.m_CommitterName, committerEmail);
104 if (CStringUtils::StartsWith(refName, L"refs/heads/"))
105 ref.m_Description = descriptions[refName.Mid(static_cast<int>(wcslen(L"refs/heads/")))];
107 map.emplace(refName, ref);
110 return 0;