vcprompt / src / svn.c

/*
 * Copyright (C) 2009-2013, Gregory P. Ward and contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "common.h"
#include "svn.h"

#include <ctype.h>

static int
svn_probe(vccontext_t *context)
{
    return isdir(".svn");
}

static result_t*
svn_get_info(vccontext_t *context)
{
    result_t *result = init_result();
    char buf[1024];

    if (!read_first_line(".svn/entries", buf, 1024)) {
        debug("failed to read from .svn/entries: assuming not an svn repo");
        goto err;
    }
    else {
        FILE *fp;
        fp = fopen(".svn/entries", "r");
        char line[1024];

        // Check the version
        if (fgets(line, sizeof(line), fp)) {
            if(isdigit(line[0])) {
                // Custom file format (working copy created by svn >= 1.4)

                // Read and discard line 2 (name), 3 (entries kind)
                if (fgets(line, sizeof(line), fp) == NULL ||
                    fgets(line, sizeof(line), fp) == NULL) {
                    debug("early EOF reading .svn/entries");
                    fclose(fp);
                    goto err;
                }

                // Get the revision number
                if (fgets(line, sizeof(line), fp)) {
                    chop_newline(line);
                    result->revision = strdup(line);
                    debug("read a svn revision from .svn/entries: '%s'", line);
                }
                else {
                    debug("early EOF: expected revision number");
                    fclose(fp);
                    goto err;
                }
            }
            else {
                // XML file format (working copy created by svn < 1.4)
                char rev[100];
                char *marker = "revision=";
                char *p = NULL;
                while (fgets(line, sizeof(line), fp))
                    if ((p = strstr(line, marker)) != NULL)
                        break;
                if (p == NULL) {
                    debug("no 'revision=' line found in .svn/entries");
                    goto err;
                }
                if (sscanf(p, " %*[^\"]\"%[0-9]\"", rev) == 1) {
                    result_set_revision(result, rev, -1);
                    debug("read svn revision from .svn/entries: '%s'", rev);
                }
            }
        }
        fclose(fp);
    }
    return result;
 err:
    free(result);
    return NULL;
}

vccontext_t*
get_svn_context(options_t *options)
{
    return init_context("svn", options, svn_probe, svn_get_info);
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.