First drop the game's core mechanic that compiles.
This commit is contained in:
commit
5f87d9846c
11 changed files with 607 additions and 0 deletions
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
.*.sw*
|
||||||
|
.DS_Store
|
||||||
|
*.sqlite3
|
||||||
|
*.sqlite3-wal
|
||||||
|
*.sqlite3-shm
|
||||||
|
debug
|
||||||
|
coverage/
|
||||||
|
.coverage
|
||||||
|
builddir
|
||||||
|
subprojects
|
||||||
|
*.csv
|
||||||
|
*.exe
|
1
LICENSE
Normal file
1
LICENSE
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Copyright (C) 2024 Zed A. Shaw
|
38
README.md
Normal file
38
README.md
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
A game I'm working. It's a weird one.
|
||||||
|
|
||||||
|
Right now I've got a command that watches your files for changes, and runs a build command. It's
|
||||||
|
entirely overengineered for this purpose, but it has what I'll need later. To build it do this:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./scripts/reset_build.ps1
|
||||||
|
meson compile -C builddir
|
||||||
|
```
|
||||||
|
|
||||||
|
If you get a bad compile because of libgit2's `src/util/process.h` then do this:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cp patches/process.h subprojects/libgit2/src/util/
|
||||||
|
meson compile -C builddir
|
||||||
|
```
|
||||||
|
|
||||||
|
I don't know why it fails at this, and only on Windows but I've talked to them repeatedly and it's
|
||||||
|
mostly "works for me" responses. I also can't figure out how Meson exactly applies patches. I've
|
||||||
|
generated every possible patch I can and Meson just can't apply them.
|
||||||
|
|
||||||
|
Once it's running, we have even more annoying BS to deal with, and that's because Meson doesn't
|
||||||
|
actually statically compile efsw or libgit2. Even though I said `--default-librart=static --prefer-static` in the setup it just ignores that and makes DLLs. The "fix" for this asinine stupidity is this:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
meson devenv -C builddir
|
||||||
|
cd ..
|
||||||
|
cp builddir/watchgit .
|
||||||
|
./watchgit . "meson compile -C builddir
|
||||||
|
```
|
||||||
|
|
||||||
|
Do all that garbage and yay, this little program runs. Finally.
|
||||||
|
|
||||||
|
## Future Changes
|
||||||
|
|
||||||
|
1. If I can't figure out why libgit2 has compilation errors in `src/util/process.h` then I may just rip it out and just shell out to `git` directly.
|
||||||
|
2. Ultimately I can jsut use efsw to watch the directory for all changes, but I wanted to only focus on what's in git. Oh well.
|
||||||
|
3. I also have to find out why efsw and libgit2 refuse to compile statically. Once I do that I can static compile `watchgit` and then work on the next part of the game.
|
49
dbc.h
Normal file
49
dbc.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include <string>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace dbc {
|
||||||
|
class Error {
|
||||||
|
public:
|
||||||
|
const string message;
|
||||||
|
Error(string m) : message{m} {}
|
||||||
|
Error(const char *m) : message{m} {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CheckError : public Error {};
|
||||||
|
|
||||||
|
class SentinelError : public Error {};
|
||||||
|
class PreCondError : public Error {};
|
||||||
|
class PostCondError : public Error {};
|
||||||
|
|
||||||
|
void log(const string &message) {
|
||||||
|
fmt::print("{}\n", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sentinel(const string &message) {
|
||||||
|
string err = fmt::format("[SENTINEL!] {}\n", message);
|
||||||
|
throw SentinelError{err};
|
||||||
|
}
|
||||||
|
|
||||||
|
void pre(const string &message, std::function<bool()> tester) {
|
||||||
|
if(!tester()) {
|
||||||
|
string err = fmt::format("[PRE!] {}\n", message);
|
||||||
|
throw PreCondError{err};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void post(const string &message, std::function<bool()> tester) {
|
||||||
|
if(!tester()) {
|
||||||
|
string err = fmt::format("[POST!] {}\n", message);
|
||||||
|
throw PostCondError{err};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check(bool test, const string &message) {
|
||||||
|
if(!test) {
|
||||||
|
string err = fmt::format("[CHECK!] {}\n", message);
|
||||||
|
throw CheckError{err};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
efsw.wrap
Normal file
10
efsw.wrap
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[wrap-git]
|
||||||
|
url = https://github.com/SpartanJ/efsw.git
|
||||||
|
revision = 1.3.1
|
||||||
|
depth = 1
|
||||||
|
# patch_filename =
|
||||||
|
# patch_hash =
|
||||||
|
|
||||||
|
|
||||||
|
[provide]
|
||||||
|
efsw = efsw_dep
|
12
libgit2.wrap
Normal file
12
libgit2.wrap
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[wrap-file]
|
||||||
|
directory = libgit2-1.8.1
|
||||||
|
source_url = https://github.com/libgit2/libgit2/archive/refs/tags/v1.8.1.tar.gz
|
||||||
|
source_filename = v1.8.1.tar.gz
|
||||||
|
source_hash = 8c1eaf0cf07cba0e9021920bfba9502140220786ed5d8a8ec6c7ad9174522f8e
|
||||||
|
wrapdb_version = 2.4.1-3
|
||||||
|
# patch_filename =
|
||||||
|
# patch_hash =
|
||||||
|
|
||||||
|
|
||||||
|
[provide]
|
||||||
|
libgit2 = libgit2_dep
|
26
meson.build
Normal file
26
meson.build
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
project('lcppthw', 'cpp',
|
||||||
|
default_options: ['cpp_std=c++20'])
|
||||||
|
|
||||||
|
cmake = import('cmake')
|
||||||
|
opts = cmake.subproject_options()
|
||||||
|
opts.add_cmake_defines({
|
||||||
|
'USE_ICONV': false,
|
||||||
|
'USE_SSH': false,
|
||||||
|
'USE_NTLMCLIENT': false,
|
||||||
|
'BUILD_SHARED_LIBS': true,
|
||||||
|
'BUILD_TESTS': false,
|
||||||
|
})
|
||||||
|
libgit2_proj = cmake.subproject('libgit2', options: opts)
|
||||||
|
libgit2package_dep = libgit2_proj.dependency('libgit2package')
|
||||||
|
|
||||||
|
efsw_proj = cmake.subproject('efsw')
|
||||||
|
efsw_dep = efsw_proj.dependency('efsw')
|
||||||
|
|
||||||
|
fmt = dependency('fmt')
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
fmt, libgit2package_dep, efsw_dep,
|
||||||
|
]
|
||||||
|
|
||||||
|
executable('watchgit', 'watchgit.cpp',
|
||||||
|
dependencies: dependencies)
|
223
patches/process.h
Normal file
223
patches/process.h
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
|
* a Linking Exception. For full terms see the included COPYING file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_process_h__
|
||||||
|
#define INCLUDE_process_h__
|
||||||
|
|
||||||
|
typedef struct git_str git_str;
|
||||||
|
typedef struct git_process git_process;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int capture_in : 1,
|
||||||
|
capture_out : 1,
|
||||||
|
capture_err : 1,
|
||||||
|
exclude_env : 1;
|
||||||
|
|
||||||
|
char *cwd;
|
||||||
|
} git_process_options;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GIT_PROCESS_STATUS_NONE,
|
||||||
|
GIT_PROCESS_STATUS_NORMAL,
|
||||||
|
GIT_PROCESS_STATUS_ERROR
|
||||||
|
} git_process_result_status;
|
||||||
|
|
||||||
|
#define GIT_PROCESS_RESULT_INIT { GIT_PROCESS_STATUS_NONE }
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
git_process_result_status status;
|
||||||
|
int exitcode;
|
||||||
|
int signal;
|
||||||
|
} git_process_result;
|
||||||
|
|
||||||
|
#define GIT_PROCESS_OPTIONS_INIT { 0 }
|
||||||
|
|
||||||
|
#ifdef GIT_WIN32
|
||||||
|
# define p_pid_t DWORD
|
||||||
|
#else
|
||||||
|
# define p_pid_t pid_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new process. The command to run should be specified as the
|
||||||
|
* element of the `arg` array, execv-style. This should be the full path
|
||||||
|
* to the command to run, the PATH is not obeyed.
|
||||||
|
*
|
||||||
|
* This function will add the given environment variables (in `env`)
|
||||||
|
* to the current environment. Operations on environment variables
|
||||||
|
* are not thread safe, so you may not modify the environment during
|
||||||
|
* this call. You can avoid this by setting `exclude_env` in the
|
||||||
|
* options and providing the entire environment yourself.
|
||||||
|
*
|
||||||
|
* @param out location to store the process
|
||||||
|
* @param args the command (with arguments) to run
|
||||||
|
* @param args_len the length of the args array
|
||||||
|
* @param env environment variables to add (or NULL)
|
||||||
|
* @param env_len the length of the env len
|
||||||
|
* @param opts the options for creating the process
|
||||||
|
* @return 0 or an error code
|
||||||
|
*/
|
||||||
|
extern int git_process_new(
|
||||||
|
git_process **out,
|
||||||
|
const char **args,
|
||||||
|
size_t args_len,
|
||||||
|
const char **env,
|
||||||
|
size_t env_len,
|
||||||
|
git_process_options *opts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new process. The command to run should be specified as the
|
||||||
|
* `cmdline` option - which is the full text of the command line as it
|
||||||
|
* would be specified or run by a user. The command to run will be
|
||||||
|
* looked up in the PATH.
|
||||||
|
*
|
||||||
|
* On Unix, this will be executed by the system's shell (`/bin/sh`)
|
||||||
|
* and may contain _Bourne-style_ shell quoting rules. On Windows,
|
||||||
|
* this will be passed to `CreateProcess`, and similarly, may
|
||||||
|
* contain _Windows-style_ shell quoting rules.
|
||||||
|
*
|
||||||
|
* This function will add the given environment variables (in `env`)
|
||||||
|
* to the current environment. Operations on environment variables
|
||||||
|
* are not thread safe, so you may not modify the environment during
|
||||||
|
* this call. You can avoid this by setting `exclude_env` in the
|
||||||
|
* options and providing the entire environment yourself.
|
||||||
|
*/
|
||||||
|
extern int git_process_new_from_cmdline(
|
||||||
|
git_process **out,
|
||||||
|
const char *cmdline,
|
||||||
|
const char **env,
|
||||||
|
size_t env_len,
|
||||||
|
git_process_options *opts);
|
||||||
|
|
||||||
|
#ifdef GIT_WIN32
|
||||||
|
|
||||||
|
extern int git_process__appname(
|
||||||
|
git_str *out,
|
||||||
|
const char *cmdline);
|
||||||
|
|
||||||
|
/* Windows path parsing is tricky; this helper function is for testing. */
|
||||||
|
extern int git_process__cmdline(
|
||||||
|
git_str *out,
|
||||||
|
const char **in,
|
||||||
|
size_t in_len);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether the given string looks like a command line option (starts
|
||||||
|
* with a dash). This is useful for examining strings that will become
|
||||||
|
* cmdline arguments to ensure that they are not erroneously treated
|
||||||
|
* as an option. For example, arguments to `ssh`.
|
||||||
|
*/
|
||||||
|
static __inline__ bool git_process__is_cmdline_option(const char *str)
|
||||||
|
{
|
||||||
|
return (str && str[0] == '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the process.
|
||||||
|
*
|
||||||
|
* @param process the process to start
|
||||||
|
* @return 0 or an error code
|
||||||
|
*/
|
||||||
|
extern int git_process_start(git_process *process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the process id of the process.
|
||||||
|
*
|
||||||
|
* @param out pointer to a pid_t to store the process id
|
||||||
|
* @param process the process to query
|
||||||
|
* @return 0 or an error code
|
||||||
|
*/
|
||||||
|
extern int git_process_id(p_pid_t *out, git_process *process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read from the process's stdout. The process must have been created with
|
||||||
|
* `capture_out` set to true.
|
||||||
|
*
|
||||||
|
* @param process the process to read from
|
||||||
|
* @param buf the buf to read into
|
||||||
|
* @param count maximum number of bytes to read
|
||||||
|
* @return number of bytes read or an error code
|
||||||
|
*/
|
||||||
|
extern ssize_t git_process_read(git_process *process, void *buf, size_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read from the process's stderr. The process must have been created with
|
||||||
|
* `capture_err` set to true.
|
||||||
|
*
|
||||||
|
* @param process the process to read from
|
||||||
|
* @param buf the buf to read into
|
||||||
|
* @param count maximum number of bytes to read
|
||||||
|
* @return number of bytes read or an error code
|
||||||
|
*/
|
||||||
|
extern ssize_t git_process_read_err(git_process *process, void *buf, size_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to the process's stdin. The process must have been created with
|
||||||
|
* `capture_in` set to true.
|
||||||
|
*
|
||||||
|
* @param process the process to write to
|
||||||
|
* @param buf the buf to write
|
||||||
|
* @param count maximum number of bytes to write
|
||||||
|
* @return number of bytes written or an error code
|
||||||
|
*/
|
||||||
|
extern ssize_t git_process_write(git_process *process, const void *buf, size_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the process to finish.
|
||||||
|
*
|
||||||
|
* @param result the result of the process or NULL
|
||||||
|
* @param process the process to wait on
|
||||||
|
*/
|
||||||
|
extern int git_process_wait(git_process_result *result, git_process *process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the input pipe from the child.
|
||||||
|
*
|
||||||
|
* @param process the process to close the pipe on
|
||||||
|
*/
|
||||||
|
extern int git_process_close_in(git_process *process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the output pipe from the child.
|
||||||
|
*
|
||||||
|
* @param process the process to close the pipe on
|
||||||
|
*/
|
||||||
|
extern int git_process_close_out(git_process *process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the error pipe from the child.
|
||||||
|
*
|
||||||
|
* @param process the process to close the pipe on
|
||||||
|
*/
|
||||||
|
extern int git_process_close_err(git_process *process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close all resources that are used by the process. This does not
|
||||||
|
* wait for the process to complete.
|
||||||
|
*
|
||||||
|
* @parma process the process to close
|
||||||
|
*/
|
||||||
|
extern int git_process_close(git_process *process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place a human-readable error message in the given git buffer.
|
||||||
|
*
|
||||||
|
* @param msg the buffer to store the message
|
||||||
|
* @param result the process result that produced an error
|
||||||
|
*/
|
||||||
|
extern int git_process_result_msg(git_str *msg, git_process_result *result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a process structure
|
||||||
|
*
|
||||||
|
* @param process the process to free
|
||||||
|
*/
|
||||||
|
extern void git_process_free(git_process *process);
|
||||||
|
|
||||||
|
#endif
|
14
scripts/reset_build.ps1
Normal file
14
scripts/reset_build.ps1
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
mv .\subprojects\packagecache .
|
||||||
|
rm -recurse -force .\subprojects\,.\builddir\
|
||||||
|
mkdir subprojects
|
||||||
|
mv .\packagecache .\subprojects\
|
||||||
|
cp *.wrap subprojects
|
||||||
|
# cp -recurse -force packagefiles subprojects
|
||||||
|
mkdir builddir
|
||||||
|
meson wrap install fmt
|
||||||
|
meson wrap install sqlite3
|
||||||
|
meson wrap install sqlitecpp
|
||||||
|
meson wrap install ftxui
|
||||||
|
# $env:CC="clang"
|
||||||
|
# $env:CXX="clang++"
|
||||||
|
meson setup --default-library=static --prefer-static builddir
|
14
scripts/reset_build.sh
Normal file
14
scripts/reset_build.sh
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
mv -f ./subprojects/packagecache .
|
||||||
|
rm -rf subprojects builddir
|
||||||
|
mkdir subprojects
|
||||||
|
mv packagecache ./subprojects/
|
||||||
|
mkdir builddir
|
||||||
|
cp *.wrap subprojects
|
||||||
|
meson wrap install fmt
|
||||||
|
meson wrap install sqlite3
|
||||||
|
meson wrap install sqlitecpp
|
||||||
|
meson wrap install ftxui
|
||||||
|
meson setup builddir
|
208
watchgit.cpp
Normal file
208
watchgit.cpp
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <fstream>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
#include <iterator>
|
||||||
|
#include <ctime>
|
||||||
|
#include "dbc.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "test.hpp"
|
||||||
|
#include <git2.h>
|
||||||
|
#include <efsw/efsw.hpp>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace fmt;
|
||||||
|
|
||||||
|
#define BUF_MAX 1024
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No idea what the semantics of this are. Will need
|
||||||
|
* to research git's dumb terminology to figure out why
|
||||||
|
* they have 4 different versions of the path for status.
|
||||||
|
*/
|
||||||
|
const char *unfuck_path(const git_status_entry *entry) {
|
||||||
|
if(entry->head_to_index != nullptr) {
|
||||||
|
if(entry->head_to_index->new_file.path) {
|
||||||
|
return entry->head_to_index->new_file.path;
|
||||||
|
} else {
|
||||||
|
return entry->head_to_index->old_file.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entry->index_to_workdir != nullptr) {
|
||||||
|
if(entry->index_to_workdir->new_file.path) {
|
||||||
|
return entry->index_to_workdir->new_file.path;
|
||||||
|
} else {
|
||||||
|
return entry->index_to_workdir->old_file.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_status(const git_status_entry *entry, unsigned int status_flags, vector<string> &updates) {
|
||||||
|
const char *path = unfuck_path(entry);
|
||||||
|
|
||||||
|
if(status_flags & GIT_STATUS_WT_NEW
|
||||||
|
|| status_flags & GIT_STATUS_INDEX_NEW)
|
||||||
|
{
|
||||||
|
updates.push_back(string{path});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status_flags & GIT_STATUS_WT_MODIFIED
|
||||||
|
|| status_flags & GIT_STATUS_INDEX_MODIFIED)
|
||||||
|
{
|
||||||
|
updates.push_back(string{path});
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to confirm this gets the new name
|
||||||
|
if(status_flags & GIT_STATUS_WT_RENAMED
|
||||||
|
|| status_flags & GIT_STATUS_INDEX_RENAMED)
|
||||||
|
{
|
||||||
|
updates.push_back(string{path});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateListener : public efsw::FileWatchListener {
|
||||||
|
public:
|
||||||
|
bool changes = false;
|
||||||
|
|
||||||
|
void handleFileAction(efsw::WatchID watchid,
|
||||||
|
const std::string& dir,
|
||||||
|
const std::string& filename,
|
||||||
|
efsw::Action action,
|
||||||
|
std::string oldFilename) override
|
||||||
|
{
|
||||||
|
changes = true;
|
||||||
|
|
||||||
|
switch(action) {
|
||||||
|
case efsw::Actions::Add:
|
||||||
|
print("ADD {} {} {}\n", dir, filename, oldFilename);
|
||||||
|
break;
|
||||||
|
case efsw::Actions::Delete:
|
||||||
|
print("DEL {} {} {}\n", dir, filename, oldFilename);
|
||||||
|
break;
|
||||||
|
case efsw::Actions::Modified:
|
||||||
|
print("MOD {} {} {}\n", dir, filename, oldFilename);
|
||||||
|
break;
|
||||||
|
case efsw::Actions::Moved:
|
||||||
|
print("MOV {} {} {}\n", dir, filename, oldFilename);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dbc::sentinel("Unknown efsw action.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_state() {
|
||||||
|
changes = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void list_git_changes(git_repository* repo) {
|
||||||
|
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
|
||||||
|
git_status_list *statuses = nullptr;
|
||||||
|
|
||||||
|
//TODO: does this leak?
|
||||||
|
int err = git_status_list_new(&statuses, repo, &opts);
|
||||||
|
dbc::check(err == 0, git_error_last()->message);
|
||||||
|
size_t count = git_status_list_entrycount(statuses);
|
||||||
|
|
||||||
|
vector<string> updates;
|
||||||
|
|
||||||
|
for(size_t i=0; i < count; i++) {
|
||||||
|
const git_status_entry *entry = git_status_byindex(statuses, i);
|
||||||
|
add_status(entry, entry->status, updates);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(string path : updates) {
|
||||||
|
print("PATH {}\n", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_build(const char* command) {
|
||||||
|
regex err_re("(.*?):([0-9]+):([0-9]+):\\s*(.*?):\\s*(.*)");
|
||||||
|
char buffer[BUF_MAX]; // BUF_MAX is a define already?
|
||||||
|
smatch err;
|
||||||
|
ofstream stats_out;
|
||||||
|
stats_out.open("stats.csv", ios::out | ios::app);
|
||||||
|
auto t = time(nullptr);
|
||||||
|
auto tm = *std::gmtime(&t);
|
||||||
|
|
||||||
|
dbc::check(stats_out.good(), "Error opening stats.csv file.");
|
||||||
|
dbc::pre("simple test", [&]() { return stats_out.good(); });
|
||||||
|
|
||||||
|
FILE *build_out = popen(command, "r");
|
||||||
|
dbc::check(build_out != nullptr, "Failed to run command.");
|
||||||
|
|
||||||
|
while(fgets(buffer, BUF_MAX, build_out) != nullptr) {
|
||||||
|
string line(buffer); // yeah, that's probably a problem
|
||||||
|
|
||||||
|
print("{}\n", line);
|
||||||
|
if(regex_match(line, err, err_re)) {
|
||||||
|
string file_name = err[1].str();
|
||||||
|
string line = err[2].str();
|
||||||
|
string col = err[3].str();
|
||||||
|
string type = err[4].str();
|
||||||
|
string message = err[5].str();
|
||||||
|
|
||||||
|
stats_out << put_time(&tm, "%FT%TZ");
|
||||||
|
stats_out << format(",{},{},{},{},{}\n", file_name, line, col, type, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stats_out.close();
|
||||||
|
dbc::post("a post test", [&]() { return !stats_out.is_open(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
git_repository* repo = nullptr;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dbc::check(argc == 3, "USAGE: watchgit PATH BUILD_CMD");
|
||||||
|
const char *git_path = argv[1];
|
||||||
|
const char *build_cmd = argv[2];
|
||||||
|
|
||||||
|
print("Using build command: {}", build_cmd);
|
||||||
|
efsw::FileWatcher* fileWatcher = new efsw::FileWatcher();
|
||||||
|
dbc::check(fileWatcher != nullptr, "Failed to create filewatcher.");
|
||||||
|
|
||||||
|
git_libgit2_init();
|
||||||
|
|
||||||
|
int err = git_repository_open(&repo, git_path);
|
||||||
|
dbc::check(err == 0, git_error_last()->message);
|
||||||
|
|
||||||
|
UpdateListener* listener = new UpdateListener();
|
||||||
|
dbc::check(listener != nullptr, "Failed to create listener.");
|
||||||
|
|
||||||
|
print("Watching directory {} for changes...\n", git_path);
|
||||||
|
efsw::WatchID wid = fileWatcher->addWatch(git_path, listener, true);
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
fileWatcher->watch();
|
||||||
|
|
||||||
|
if(listener->changes) {
|
||||||
|
sleep(1);
|
||||||
|
list_git_changes(repo);
|
||||||
|
listener->reset_state();
|
||||||
|
run_build(build_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
git_libgit2_shutdown();
|
||||||
|
} catch(dbc::Error &err) {
|
||||||
|
print("ERROR: {}\n", err.message);
|
||||||
|
if(repo != nullptr) git_repository_free(repo);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
git_libgit2_shutdown();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue