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.
22 #include "GitRevRefBrowser.h"
23 #include "StringUtils.h"
24 #include "GitMailmap.h"
26 GitRevRefBrowser::GitRevRefBrowser() : GitRev()
30 void GitRevRefBrowser::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
)
40 MAP_STRING_STRING descriptions
;
41 g_Git
.GetBranchDescriptions(descriptions
);
47 args
= L
" --merged HEAD";
50 args
= L
" --no-merged HEAD";
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
));
57 if (g_Git
.Run(cmd
, &allRefs
, &err
, CP_UTF8
))
63 while (!(singleRef
= allRefs
.Tokenize(L
"\03", linePos
)).IsEmpty())
65 singleRef
.TrimLeft(L
"\r\n");
67 CString refName
= singleRef
.Tokenize(L
"\04", valuePos
);
69 if (refName
.IsEmpty() || (filterCallback
&& !filterCallback(refName
)))
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
;
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
);