winprefs v0.3.2
A registry exporter for programmers.
Loading...
Searching...
No Matches
git_branch.c
1#include "git_branch.h"
2#include "constants.h"
3
4// Based on https://stackoverflow.com/a/35658917/374110
5wchar_t *get_git_branch(const wchar_t *git_dir_arg,
6 size_t git_dir_arg_len,
7 const wchar_t *work_tree_arg,
8 size_t work_tree_arg_len) {
9 char *result = malloc(255);
10 wchar_t *cmd, *w_result;
11 cmd = w_result = nullptr;
12 if (!result) { // LCOV_EXCL_START
13 goto fail;
14 } // LCOV_EXCL_STOP
15 memset(result, 0, 255);
16 HANDLE pipe_read, pipe_write;
17 SECURITY_ATTRIBUTES sa_attr = {.lpSecurityDescriptor = nullptr,
18 .bInheritHandle =
19 true, // Pipe handles are inherited by child process.
20 .nLength = sizeof(SECURITY_ATTRIBUTES)};
21 // Create a pipe to get results from child's stdout.
22 if (!CreatePipe(&pipe_read, &pipe_write, &sa_attr, 0)) {
23 goto fail;
24 }
25 STARTUPINFO si = {.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES,
26 .hStdOutput = pipe_write,
27 .hStdError = pipe_write,
28 .wShowWindow = SW_HIDE};
29 PROCESS_INFORMATION pi = {0};
30 size_t cmd_len = git_dir_arg_len + work_tree_arg_len + 30;
31 cmd = calloc(cmd_len, WL);
32 if (!cmd) { // LCOV_EXCL_START
33 CloseHandle(pipe_write);
34 CloseHandle(pipe_read);
35 goto fail;
36 } // LCOV_EXCL_STOP
37 wmemset(cmd, L'\0', cmd_len);
38 _snwprintf(
39 cmd, cmd_len, TEXT("git.exe %ls %ls branch --show-current"), git_dir_arg, work_tree_arg);
40 cmd[cmd_len - 1] = L'\0';
41 bool ret = CreateProcess(
42 nullptr, cmd, nullptr, nullptr, true, CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi);
43 if (!ret) {
44 CloseHandle(pipe_write);
45 CloseHandle(pipe_read);
46 goto fail;
47 }
48 bool proc_ended = false;
49 for (; !proc_ended;) {
50 // Give some time slice (50 ms), so we won't waste 100% CPU.
51 proc_ended = WaitForSingleObject(pi.hProcess, 50) == WAIT_OBJECT_0;
52 // Even if process exited - we continue reading, if
53 // there is some data available over pipe.
54 for (;;) {
55 char buf[255];
56 memset(buf, L'\0', 255);
57 DWORD read = 0;
58 DWORD avail = 0;
59 if (!PeekNamedPipe(pipe_read, nullptr, 0, nullptr, &avail, nullptr) || !avail ||
60 !ReadFile(pipe_read, buf, min(sizeof(buf) - 1, avail), &read, nullptr) || !read) {
61 break;
62 }
63 buf[min(sizeof(buf) - 1, avail)] = L'\0';
64 if (avail) {
65 strncat(result, buf, proc_ended ? avail - 1 : avail); // Strip newline
66 }
67 }
68 }
69 CloseHandle(pipe_write);
70 CloseHandle(pipe_read);
71 CloseHandle(pi.hProcess);
72 CloseHandle(pi.hThread);
73 size_t res_len = strlen(result);
74 int w_len = MultiByteToWideChar(CP_UTF8, 0, result, (int)res_len, nullptr, 0);
75 w_result = calloc((size_t)w_len + 1, WL);
76 if (!w_result) { // LCOV_EXCL_START
77 goto fail;
78 } // LCOV_EXCL_STOP
79 MultiByteToWideChar(CP_UTF8, 0, result, (int)res_len, w_result, w_len);
80 w_result[w_len] = L'\0';
81 goto cleanup;
82fail:
83 w_result = nullptr;
84cleanup:
85 free(cmd);
86 free(result);
87 return w_result;
88}