#include <malloc.h>
#include <process.h>
#include <stdio.h>
#include <string.h>
#include <syslimits.h>
#include <sys/cygwin.h>
#include <unistd.h>

// Experimental svn interceptor, to help debugging
// debug NetBeans vs. Cygwin svn problems. See
// http://www.clausbrod.de/Blog/DefinePrivatePublic20100424NetBeansVersusCygwin
// for details.
//
// Claus Brod, April 2010

char *convpath(const char *from) {
  if (0 == strchr(from, '\\')) {
    return strdup(from);
  }
  ssize_t len = cygwin_conv_path(CCP_WIN_A_TO_POSIX, from, NULL, 0);
  char *to = (char *) malloc(len);
  if (0 == cygwin_conv_path(CCP_WIN_A_TO_POSIX, from, to, len)) {
    return to;
  }
  free(to);
  return NULL;
}

char *patchfile(const char *from) {
  FILE *ffrom = fopen(from, "r");
  if (!ffrom)
    return NULL;

#define SUFFIX "__hungo"
  char *to = (char *) malloc(PATH_MAX + sizeof (SUFFIX));
  strncpy(to, from, PATH_MAX);
  strcat(to, SUFFIX);

  FILE *fto = fopen(to, "w");
  if (!fto) {
    fclose(ffrom);
    return NULL;
  }

  char buf[2048];
  while (NULL != fgets(buf, sizeof (buf), ffrom)) {
    char *converted = convpath(buf);
    if (converted) {
      fputs(converted, fto);
      free(converted);
    }
  }

  fclose(fto);
  fclose(ffrom);
  return to;
}

int main(int argc, char *argv[]) {
  char **args = (char **) calloc(argc + 1, sizeof (char*));

  // original svn client is in /bin
  args[0] = "/bin/svn.exe";

  for (int i = 1; i < argc; i++) {
    args[i] = convpath(argv[i]);
  }

  // look for --targets
  for (int i = 0; i < argc; i++) {
    if (0 == strcmp(args[i], "--targets")) {
      char *to = patchfile(args[i + 1]);
      if (to) args[i + 1] = to;
    }
  }

  int ret = spawnv(_P_WAIT, args[0], args);

  // Remove temporary --targets
  for (int i = 0; i < argc; i++) {
    if (0 == strcmp(args[i], "--targets")) {
      unlink(args[i + 1]);
    }
  }

  return ret;
}
