-
Notifications
You must be signed in to change notification settings - Fork 2
/
coutcflt.cpp
executable file
·174 lines (157 loc) · 4.95 KB
/
coutcflt.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
* Checkout conflict display via notifications.
*/
#include <stdafx.h>
typedef struct _LGitCheckoutNotifyResults {
/* Can just be a list of strings. We don't use the git_diff_file* yet */
std::set<std::string> conflicts;
} LGitCheckoutNotifyResults;
typedef struct _LGitCheckoutNotifyParams {
LGitContext *ctx;
LGitCheckoutNotifyResults *results;
} LGitCheckoutNotifyParams;
static int LGitCheckoutNotify(git_checkout_notify_t why,
const char *path,
const git_diff_file *baseline,
const git_diff_file *target,
const git_diff_file *workdir,
void *payload)
{
LGitCheckoutNotifyResults *results = (LGitCheckoutNotifyResults*)payload;
if (payload == NULL) {
return GIT_EUSER;
}
switch (why) {
case GIT_CHECKOUT_NOTIFY_CONFLICT:
results->conflicts.insert(std::string(path));
return 0;
/* XXX: We may care about this one */
/* case GIT_CHECKOUT_NOTIFY_DIRTY: // changed but no action */
/* case: GIT_CHECKOUT_NOTIFY_NONE: // no action required */
/* case: GIT_CHECKOUT_NOTIFY_UPDATED: // cleanly replaced */
/* case: GIT_CHECKOUT_NOTIFY_UNTRACKED: */
/* case: GIT_CHECKOUT_NOTIFY_IGNORED: */
default:
return 0;
}
}
/* Allocate and set the callback */
SCCRTN LGitInitCheckoutNotifyCallbacks(LGitContext *ctx, HWND hwnd, git_checkout_options *co_opts)
{
LGitCheckoutNotifyResults *results = new LGitCheckoutNotifyResults;
if (results == NULL) {
return SCC_E_UNKNOWNERROR;
}
/* XXX: Do we care about dirty? */
co_opts->notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT;
co_opts->notify_cb = LGitCheckoutNotify;
co_opts->notify_payload = results;
return SCC_OK;
}
/* could use rework if we change based on params to callback */
static LVCOLUMN path_column = {
LVCF_TEXT | LVCF_WIDTH, 0, 125, "Path"
};
static void InitCheckoutNotifyView(HWND hwnd, LGitCheckoutNotifyParams* params)
{
HWND lv = GetDlgItem(hwnd, IDC_CHECKOUT_NOTIFY_LIST);
ListView_SetExtendedListViewStyle(lv, LVS_EX_FULLROWSELECT
| LVS_EX_HEADERDRAGDROP
| LVS_EX_LABELTIP);
ListView_SetUnicodeFormat(lv, TRUE);
SendMessage(lv, WM_SETFONT, (WPARAM)params->ctx->listviewFont, TRUE);
ListView_InsertColumn(lv, 0, &path_column);
/* Initialize the system image list */
HIMAGELIST sil = LGitGetSystemImageList();
ListView_SetImageList(lv, sil, LVSIL_SMALL);
}
static void FillCheckoutNotifyView(HWND hwnd, LGitCheckoutNotifyParams* params)
{
HWND lv = GetDlgItem(hwnd, IDC_CHECKOUT_NOTIFY_LIST);
std::set<std::string> *conflicts = ¶ms->results->conflicts;
std::set<std::string>::iterator i;
int index = 0;
for (i = conflicts->begin(); i != conflicts->end(); i++) {
SHFILEINFOW sfi;
ZeroMemory(&sfi, sizeof(sfi));
LVITEMW lvi;
wchar_t buf[1024], absolute[1024];
ZeroMemory(&lvi, sizeof(LVITEMW));
lvi.mask = LVIF_TEXT | LVIF_IMAGE;
LGitUtf8ToWide(i->c_str(), buf, 1024);
/* need the absolute path for the icon unfortunately */
wcslcpy(absolute, params->ctx->workdir_path_utf16, 1024);
wcslcat(absolute, buf, 1024);
LGitTranslateStringCharsW(absolute, L'/', L'\\');
SHGetFileInfoW(absolute, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
lvi.iImage = sfi.iIcon;
lvi.pszText = buf;
lvi.iItem = index++;
lvi.iSubItem = 0;
SendMessage(lv, LVM_INSERTITEMW, 0, (LPARAM)&lvi);
if (lvi.iItem == -1) {
LGitLog(" ! ListView_InsertItem failed\n");
continue;
}
}
ListView_SetColumnWidth(lv, 0, LVSCW_AUTOSIZE_USEHEADER);
}
static BOOL CALLBACK CheckoutNotifyDialogProc(HWND hwnd,
unsigned int iMsg,
WPARAM wParam,
LPARAM lParam)
{
LGitCheckoutNotifyParams *param;
switch (iMsg) {
case WM_INITDIALOG:
param = (LGitCheckoutNotifyParams*)lParam;
SetWindowLong(hwnd, GWL_USERDATA, (long)param); /* XXX: 64-bit... */
InitCheckoutNotifyView(hwnd, param);
FillCheckoutNotifyView(hwnd, param);
/* Finally beep like we're a system error */
MessageBeep(MB_ICONERROR);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hwnd, 1);
return TRUE;
}
return FALSE;
default:
return FALSE;
}
}
/* Free and display any messages as needed */
SCCRTN LGitFinishCheckoutNotify(LGitContext *ctx, HWND hwnd, git_checkout_options *co_opts)
{
if (co_opts->notify_payload == NULL) {
return SCC_OK;;
}
LGitCheckoutNotifyResults *results = (LGitCheckoutNotifyResults*)co_opts->notify_payload;
if (results->conflicts.size() == 0) {
/* nothing to report */
goto fin;
}
LGitCheckoutNotifyParams params;
params.ctx = ctx;
params.results = results;
switch (DialogBoxParamW(ctx->dllInst,
MAKEINTRESOURCEW(IDD_CHECKOUT_NOTIFY),
hwnd,
CheckoutNotifyDialogProc,
(LPARAM)¶ms)) {
case 0:
case -1:
LGitLog(" ! Uh-oh, dialog error\n");
return SCC_E_UNKNOWNERROR;
default:
break;
}
fin:
/* now free */
delete results;
co_opts->notify_payload = NULL;
return SCC_OK;
}