2 #include "../common/cache.h"
3 #include "../common/exec.h"
6 #include "../common/menuengine.h"
12 * this flag, not defined in mingw's ShlObj.h, is a hint that the file
13 * has changed since the last call to GetItemData
15 #define SHCDF_UPDATEITEM 0x00000001
18 /* convenience macro, not defined in mingw's OleAuto.h */
19 #define V_I1REF(X) V_UNION(X, pcVal)
23 #define CHEETAH_COLUMN_FLAGS (SHCOLSTATE_TYPE_STR)
26 * If a non-standard FMT is specified, the column will be accessible
27 * only in repo folders. But if FMTID_SummaryInformation is used,
28 * the column's info will be "merged" into CHEETAH_PID_* and may
29 * be visible in the Details on folder's task pane
31 #define CHEETAH_FMTID IID_git_columns
34 * column's id, that can be matched to one of standard FMTs
35 * for example, if FMTID is FMTID_SummaryInformation than
36 * PID can be PIDSI_AUTHOR, so the status is provided in the
37 * Author column and visible in the Details
39 #define CHEETAH_STATUS_PID 0
41 /* names and descriptions MUST be wchar * */
42 #define CHEETAH_STATUS_NAME L"Git Status"
43 #define CHEETAH_STATUS_DESC L"Status of the file in a Git repository"
45 STDMETHODIMP
initialize_columns(void *p
, LPCSHCOLUMNINIT psci
)
47 struct git_data
*this_
= ((struct git_columns
*)p
)->git_data
;
50 wcstombs(this_
->name
, psci
->wszFolder
, MAX_PATH
);
53 * don't try to do anything about cache here, because
54 * we're called even if get_item_data will not be called
56 status
= exec_program(this_
->name
, NULL
, NULL
, WAITMODE
,
57 "git", "rev-parse", "--show-prefix", NULL
);
60 * if something went terribly wrong or not a repo,
61 * return E_FAIL to prevent calls to get_column_info
63 return status
? E_FAIL
: S_OK
;
66 STDMETHODIMP
get_column_info(void *p
, DWORD dwIndex
, SHCOLUMNINFO
*psci
)
68 struct git_data
*this_
= ((struct git_columns
*)p
)->git_data
;
70 /* do NOT FORGET to increase this when adding more columns */
74 psci
->scid
.fmtid
= CHEETAH_FMTID
;
75 psci
->scid
.pid
= CHEETAH_STATUS_PID
;
77 psci
->fmt
= LVCFMT_LEFT
;
79 psci
->csFlags
= CHEETAH_COLUMN_FLAGS
;
81 lstrcpynW(psci
->wszTitle
,
82 CHEETAH_STATUS_NAME
, MAX_COLUMN_NAME_LEN
);
83 lstrcpynW(psci
->wszDescription
,
84 CHEETAH_STATUS_DESC
, MAX_COLUMN_DESC_LEN
);
89 static int cache_others(char *wd
, struct strbuf
*cache
)
96 strbuf_init(cache
, 0);
97 status
= exec_program(wd
, cache
, NULL
, WAITMODE
,
98 "git", "ls-files", "-z", "--others", "--exclude-standard",
101 /* something went terribly wrong or not a repo */
103 strbuf_release(cache
);
108 * cache files' status, and return non-zero on the first failure
109 * because if something goes wrong, there is no need to try other statuses
111 static int cache(struct git_data
*this_
)
114 if (status
= cache_others(this_
->name
, &this_
->other_files
))
117 /* if everything succeeded, return success */
121 static char *parse_others(struct strbuf
*cache
, char *file
)
123 char *start
= cache
->buf
;
125 if (!stricmp(file
, start
))
128 start
+= strlen(start
) + 1;
134 static char *parse_status(struct git_data
*this_
, char *file
)
138 if (result
= parse_others(&this_
->other_files
, file
))
141 /* if no status was found, return NULL string */
146 STDMETHODIMP
get_item_data(void *p
,
148 LPCSHCOLUMNDATA pscd
,
151 struct git_data
*this_
= ((struct git_columns
*)p
)->git_data
;
152 char file_path
[MAX_PATH
], *file
= file_path
;
155 /* directories don't have status */
156 if (pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
159 /* update cache and bail out on failure */
163 if (pscd
->dwFlags
& SHCDF_UPDATEITEM
) {
165 * we can add the file to the usual ls-files
166 * or we can refresh the whole cache
170 wcstombs(file
, pscd
->wszFile
, MAX_PATH
);
171 file
+= strlen(this_
->name
) + 1;
173 /* get the status from cache and return if any */
174 if (result
= parse_status(this_
, file
)) {
175 V_VT(pvarData
) = VT_LPSTR
;
176 V_I1REF(pvarData
) = result
;
183 DEFINE_STANDARD_METHODS(git_columns
)
185 struct git_columns_virtual_table git_columns_virtual_table
= {
186 query_interface_git_columns
,