svnclient.cpp

来自「linux subdivision ying gai ke yi le ba」· C++ 代码 · 共 2,291 行 · 第 1/5 页

CPP
2,291
字号
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 */
// SVNClient.cpp: implementation of the SVNClient class.
//
//////////////////////////////////////////////////////////////////////

#include "SVNClient.h"
#include "JNIUtil.h"
#include "Notify.h"
#include "Prompter.h"
#include "Pool.h"
#include "Targets.h"
#include "Revision.h"
#include "BlameCallback.h"
#include "JNIByteArray.h"
#include "CommitMessage.h"
#include <svn_client.h>
#include <svn_sorts.h>
#include <svn_time.h>
#include <svn_config.h>
#include <svn_io.h>
#include <svn_path.h>
#include "svn_private_config.h"
#include "../include/org_tigris_subversion_javahl_StatusKind.h"
#include "../include/org_tigris_subversion_javahl_Revision.h"
#include "../include/org_tigris_subversion_javahl_NodeKind.h"
#include "../include/org_tigris_subversion_javahl_ScheduleKind.h"
#include "JNIStringHolder.h"
#include <vector>
#include <iostream>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
struct log_msg_baton
{
    const char *message;
    CommitMessage *messageHandler;
};

SVNClient::SVNClient()
{
    m_notify = NULL;
    m_prompter = NULL;
    m_commitMessage = NULL;
}

SVNClient::~SVNClient()
{
    delete m_notify;
    delete m_prompter;
}

jlong SVNClient::getCppAddr()
{
    return reinterpret_cast<jlong>(this);
}

SVNClient * SVNClient::getCppObject(jobject jthis)
{
    static jfieldID fid = 0;
    JNIEnv *env = JNIUtil::getEnv();
    if(fid == 0)
    {
        jclass clazz = env->FindClass(JAVA_PACKAGE"/SVNClient");
        if(JNIUtil::isJavaExceptionThrown())
        {
            return NULL;
        }
        fid = env->GetFieldID(clazz, "cppAddr", "J");
        if(JNIUtil::isJavaExceptionThrown())
        {
            return NULL;
        }
    }

    jlong cppAddr = env->GetLongField(jthis, fid);
    if(JNIUtil::isJavaExceptionThrown())
    {
        return NULL;
    }
    return reinterpret_cast<SVNClient*>(cppAddr);

}

void SVNClient::dispose(jobject jthis)
{
    delete this;
    static jfieldID fid = 0;
    JNIEnv *env = JNIUtil::getEnv();
    if(fid == 0)
    {
        jclass clazz = env->FindClass(JAVA_PACKAGE"/SVNClient");
        if(JNIUtil::isJavaExceptionThrown())
        {
            return;
        }
        fid = env->GetFieldID(clazz, "cppAddr", "J");
        if(JNIUtil::isJavaExceptionThrown())
        {
            return;
        }
    }

    env->SetLongField(jthis, fid, 0);
    if(JNIUtil::isJavaExceptionThrown())
    {
        return;
    }
}

void SVNClient::finalize()
{
    JNIUtil::putFinalizedClient(this);
}

const char * SVNClient::getLastPath()
{
    return m_lastPath.c_str();
}

/**
 * List directory entries of a URL
 */
jobjectArray SVNClient::list(const char *url, Revision &revision, bool recurse)
{
    Pool requestPool;
    svn_client_ctx_t *ctx = getContext(NULL);
    if(ctx == NULL)
    {
        return NULL;
    }

    if(url == NULL)
    {
        JNIUtil::throwNullPointerException("path or url");
        return NULL;
    }

    Path urlPath(url);
    svn_error_t *Err = urlPath.error_occured();
    if(Err != NULL)
    {
        JNIUtil::handleSVNError(Err);
        return NULL;
    }
    
    apr_hash_t *dirents;
    Err = svn_client_ls (&dirents, urlPath.c_str(), 
                         const_cast<svn_opt_revision_t*>(revision.revision ()),
                         recurse, ctx, requestPool.pool());
    if (Err == NULL)
    {
        apr_array_header_t *array =
               svn_sort__hash (dirents, svn_sort_compare_items_as_paths,
                               requestPool.pool());

        // create the array of DirEntry
        JNIEnv *env = JNIUtil::getEnv();
        jclass clazz = env->FindClass(JAVA_PACKAGE"/DirEntry");
        if(JNIUtil::isJavaExceptionThrown())
        {
            return NULL;
        }
        jobjectArray ret = env->NewObjectArray(array->nelts, clazz, NULL);
        if(JNIUtil::isJavaExceptionThrown())
        {
            return NULL;
        }
        env->DeleteLocalRef(clazz);
        if(JNIUtil::isJavaExceptionThrown())
        {
            return NULL;
        }

        for (int i = 0; i < array->nelts; i++)
        {
            const svn_sort__item_t *item;
            svn_dirent_t *dirent = NULL;

            item = &APR_ARRAY_IDX (array, i, const svn_sort__item_t);
            dirent = (svn_dirent_t *) item->value;

            jobject obj = createJavaDirEntry((const char *)item->key, dirent);
            env->SetObjectArrayElement(ret, i, obj);
            if(JNIUtil::isJavaExceptionThrown())
            {
                return NULL;
            }
            env->DeleteLocalRef(obj);
            if(JNIUtil::isJavaExceptionThrown())
            {
                return NULL;
            }
        }
        return ret;
    }
    else
    {
        JNIUtil::handleSVNError(Err);
        return NULL;
    }
}


struct status_entry
{
    const char *path;
    svn_wc_status_t *status;
};

struct status_baton
{
    std::vector<status_entry> statusVect;
    apr_pool_t *pool;
};


/**
 * callback for svn_client_status (used by status and singleStatus)
 */
void SVNClient::statusReceiver(void *baton, const char *path, 
                               svn_wc_status_t *status)
{
    if(JNIUtil::isJavaExceptionThrown())
        return;

    // we don't create here java Status object as we don't want too many local 
    // references
    status_baton *statusBaton = (status_baton*)baton;
    status_entry statusEntry;
    statusEntry.path = apr_pstrdup(statusBaton->pool,path);
    statusEntry.status = svn_wc_dup_status(status,statusBaton->pool);
    statusBaton->statusVect.push_back(statusEntry);
}


jobjectArray SVNClient::status(const char *path, bool descend, bool onServer, 
                               bool getAll, bool noIgnore)
{
    status_baton statusBaton;
    Pool requestPool;
    svn_revnum_t youngest = SVN_INVALID_REVNUM;
    svn_opt_revision_t rev;

    if(path == NULL)
    {
        JNIUtil::throwNullPointerException("path");
        return NULL;
    }

    svn_client_ctx_t *ctx = getContext(NULL);
    if(ctx == NULL)
    {
        return NULL;
    }
    Path checkedPath(path);
    svn_error_t *Err = checkedPath.error_occured();
    if(Err != NULL)
    {
        JNIUtil::handleSVNError(Err);
        return NULL;
    }

    rev.kind = svn_opt_revision_unspecified;
    statusBaton.pool = requestPool.pool();

    Err = svn_client_status (
                             &youngest, checkedPath.c_str(), &rev, statusReceiver, 
                             &statusBaton, descend ? TRUE : FALSE,
                             getAll ? TRUE : FALSE,
                             onServer ? TRUE : FALSE,
                             noIgnore ? TRUE : FALSE,
                             ctx,
                             requestPool.pool());
    if (Err == NULL)
    {
        JNIEnv *env = JNIUtil::getEnv();
        int size = statusBaton.statusVect.size();
        jclass clazz = env->FindClass(JAVA_PACKAGE"/Status");
        if(JNIUtil::isJavaExceptionThrown())
        {
            return NULL;
        }
        jobjectArray ret = env->NewObjectArray(size, clazz, NULL);
        if(JNIUtil::isJavaExceptionThrown())
        {
            return NULL;
        }
        env->DeleteLocalRef(clazz);
        if(JNIUtil::isJavaExceptionThrown())
        {
            return NULL;
        }

        for(int i = 0; i < size; i++)
        {
            status_entry statusEntry = statusBaton.statusVect[i];

            jobject jStatus = createJavaStatus(statusEntry.path, 
                                               statusEntry.status);
            env->SetObjectArrayElement(ret, i, jStatus);
            if(JNIUtil::isJavaExceptionThrown())
            {
                return NULL;
            }
            env->DeleteLocalRef(jStatus);
            if(JNIUtil::isJavaExceptionThrown())
            {
                return NULL;
            }
        }
        return ret;
    }
    else
    {
        JNIUtil::handleSVNError(Err);
        return NULL;
    }
}

jobject SVNClient::singleStatus(const char *path, bool onServer)
{
    status_baton statusBaton;
    Pool requestPool;
    svn_revnum_t youngest = SVN_INVALID_REVNUM;
    svn_opt_revision_t rev;

    if(path == NULL)
    {
        JNIUtil::throwNullPointerException("path");
        return NULL;
    }

    svn_client_ctx_t *ctx = getContext(NULL);
    if(ctx == NULL)
    {
        return NULL;
    }


    rev.kind = svn_opt_revision_unspecified;
    statusBaton.pool = requestPool.pool();
    Path intPath(path);
    svn_error_t *Err = intPath.error_occured();
    if(Err != NULL)
    {
        JNIUtil::handleSVNError(Err);
        return NULL;
    }

    Err = svn_client_status (&youngest, intPath.c_str(), &rev, 
                             statusReceiver, &statusBaton,
                             FALSE,
                             TRUE,  // get_All
                             onServer ? TRUE : FALSE,     //update
                             FALSE,     //no_ignore,
                             ctx,
                             requestPool.pool());
    if(Err == NULL)
    {
        int size = statusBaton.statusVect.size();
        if (size == 0)
            return NULL;

        // when svn_client_status is used with a directory, the status of the 
        // directory itself and the status of all its direct children are 
        // returned
        // we just want the status of the directory (ie the status of the 
        // element with the shortest path)
        int j = 0;
        for (int i = 0; i < size; i++)
        {
            if (strlen(statusBaton.statusVect[i].path) < 
                   strlen(statusBaton.statusVect[j].path))
                j = i;
        }

        jobject jStatus = createJavaStatus(statusBaton.statusVect[j].path, 
                                           statusBaton.statusVect[j].status);

        return jStatus;
    }
    else
    {
         JNIUtil::handleSVNError(Err);
        return NULL;
    }
}

void SVNClient::username(const char *username)
{
    m_userName = username;
}

void SVNClient::password(const char *password)
{
    m_passWord = password;
}

void SVNClient::setPrompt(Prompter *prompter)
{
    delete m_prompter;
    m_prompter = prompter;
}

jobjectArray SVNClient::logMessages(const char *path, Revision &revisionStart,
                                    Revision &revisionEnd, bool stopOnCopy,
                                    bool discoverPaths)
{
    std::vector<jobject> logs;
    Pool requestPool;

    if(path ==NULL)
    {
        JNIUtil::throwNullPointerException("path");
        return NULL;
    }

    svn_client_ctx_t *ctx = getContext(NULL);
    if(ctx == NULL)
    {
        return NULL;
    }
    Targets target (path);
    const apr_array_header_t *targets = target.array(requestPool);
    svn_error_t *Err = target.error_occured();
    if(Err != NULL)
    {
        JNIUtil::handleSVNError(Err);
        return NULL;
    }
    Err = svn_client_log (targets,
                        revisionStart.revision (),
                        revisionEnd.revision (),
                        discoverPaths,
                        stopOnCopy,
                        messageReceiver, &logs, ctx, requestPool.pool());
    if(JNIUtil::isJavaExceptionThrown())
    {
        return NULL;
    }
    if(Err == NULL)
    {
        int size = logs.size();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?