Py::Object pysvn_client::cmd_diff( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_tmp_path }, { true, name_url_or_path }, { false, name_revision1 }, { false, name_url_or_path2 }, { false, name_revision2 }, { false, name_recurse }, { false, name_ignore_ancestry }, { false, name_diff_deleted }, #if defined( PYSVN_HAS_CLIENT_DIFF2 ) { false, name_ignore_content_type }, #endif #if defined( PYSVN_HAS_CLIENT_DIFF3 ) { false, name_header_encoding }, { false, name_diff_options }, #endif #if defined( PYSVN_HAS_CLIENT_DIFF4 ) { false, name_depth }, { false, name_relative_to_dir }, { false, name_changelists }, #endif { false, NULL } }; FunctionArguments args( "diff", args_desc, a_args, a_kws ); args.check(); std::string tmp_path( args.getUtf8String( name_tmp_path ) ); std::string path1( args.getUtf8String( name_url_or_path ) ); svn_opt_revision_t revision1 = args.getRevision( name_revision1, svn_opt_revision_base ); std::string path2( args.getUtf8String( name_url_or_path2, path1 ) ); svn_opt_revision_t revision2 = args.getRevision( name_revision2, svn_opt_revision_working ); #if defined( PYSVN_HAS_CLIENT_DIFF4 ) svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_infinity, svn_depth_infinity, svn_depth_files ); #else bool recurse = args.getBoolean( name_recurse, true ); #endif bool ignore_ancestry = args.getBoolean( name_ignore_ancestry, true ); bool diff_deleted = args.getBoolean( name_diff_deleted, true ); #if defined( PYSVN_HAS_CLIENT_DIFF2 ) bool ignore_content_type = args.getBoolean( name_ignore_content_type, false ); #endif SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_DIFF3 ) std::string header_encoding( args.getUtf8String( name_header_encoding, empty_string ) ); const char *header_encoding_ptr = APR_LOCALE_CHARSET; if( !header_encoding.empty() ) header_encoding_ptr = header_encoding.c_str(); apr_array_header_t *options = NULL; if( args.hasArg( name_diff_options ) ) { options = arrayOfStringsFromListOfStrings( args.getArg( name_diff_options ), pool ); } else { options = apr_array_make( pool, 0, sizeof( const char * ) ); } #else apr_array_header_t *options = apr_array_make( pool, 0, sizeof( const char * ) ); #endif #if defined( PYSVN_HAS_CLIENT_DIFF4 ) std::string std_relative_to_dir; const char *relative_to_dir = NULL; if( args.hasArg( name_relative_to_dir ) ) { std_relative_to_dir = args.getUtf8String( name_relative_to_dir ); relative_to_dir = std_relative_to_dir.c_str(); } apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } #endif svn_stringbuf_t *stringbuf = NULL; try { std::string norm_tmp_path( svnNormalisedIfPath( tmp_path, pool ) ); std::string norm_path1( svnNormalisedIfPath( path1, pool ) ); std::string norm_path2( svnNormalisedIfPath( path2, pool ) ); checkThreadPermission(); pysvn_apr_file output_file( pool ); pysvn_apr_file error_file( pool ); output_file.open_unique_file( norm_tmp_path ); error_file.open_unique_file( norm_tmp_path ); PythonAllowThreads permission( m_context ); #if defined( PYSVN_HAS_CLIENT_DIFF4 ) svn_error_t *error = svn_client_diff4 ( options, norm_path1.c_str(), &revision1, norm_path2.c_str(), &revision2, relative_to_dir, depth, ignore_ancestry, !diff_deleted, ignore_content_type, header_encoding_ptr, output_file.file(), error_file.file(), changelists, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_DIFF3 ) svn_error_t *error = svn_client_diff3 ( options, norm_path1.c_str(), &revision1, norm_path2.c_str(), &revision2, recurse, ignore_ancestry, !diff_deleted, ignore_content_type, header_encoding_ptr, output_file.file(), error_file.file(), m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_DIFF2 ) svn_error_t *error = svn_client_diff2 ( options, norm_path1.c_str(), &revision1, norm_path2.c_str(), &revision2, recurse, ignore_ancestry, !diff_deleted, ignore_content_type, output_file.file(), error_file.file(), m_context, pool ); #else svn_error_t *error = svn_client_diff ( options, norm_path1.c_str(), &revision1, norm_path2.c_str(), &revision2, recurse, ignore_ancestry, !diff_deleted, output_file.file(), error_file.file(), m_context, pool ); #endif permission.allowThisThread(); if( error != NULL ) throw SvnException( error ); output_file.close(); output_file.open_tmp_file(); error = svn_stringbuf_from_aprfile( &stringbuf, output_file.file(), pool ); if( error != NULL ) throw SvnException( error ); } catch( SvnException &e ) { // use callback error over ClientException m_context.checkForError( m_module.client_error ); throw_client_error( e ); } // cannot convert to Unicode as we have no idea of the encoding of the bytes return Py::String( stringbuf->data, (int)stringbuf->len ); }
int a_svn_diff (char *device_group, char *device_name, char *configured_by, char *repository_path, char *temp_working_dir, apr_pool_t *apr_pool, apr_pool_t *svn_pool) /* * * diff of a working copy and svn head (for a single file) * */ { svn_error_t* err; int int_err; apr_array_header_t *device_arr; apr_file_t *diff_outfile; apr_file_t *diff_errfile; apr_array_header_t *array; struct stat svn_diff_file_info; int svn_diff_file_size = 0; char temp_svn_path[MAXPATH]; char full_device_svn_path[MAXPATH]; char svn_diff_outfname[50]="."; char svn_diff_errfname[50]="."; svn_client_ctx_t* context; svn_error_t *svn_err; temp_svn_path[0] = 0x0; full_device_svn_path[0] = 0x0; strcat(temp_svn_path,temp_working_dir); strcat(svn_diff_outfname,device_name); strcat(svn_diff_outfname,".diff.tmp"); strcat(svn_diff_errfname,device_name); strcat(svn_diff_errfname,".diff.err.tmp"); /* if device is in the device group - add group name to the SVN diff path: */ if(strstr(device_group,"none")) snprintf(full_device_svn_path,MAXPATH,"%s/%s",repository_path,device_name); else snprintf(full_device_svn_path,MAXPATH,"%s/%s/%s",repository_path,device_group,device_name); apr_file_open(&diff_outfile, svn_diff_outfname, (APR_READ | APR_WRITE | APR_CREATE ), ( APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD | APR_FPROT_WREAD ), apr_pool); apr_file_open(&diff_errfile, svn_diff_errfname, (APR_READ | APR_WRITE | APR_CREATE ), ( APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD | APR_FPROT_WREAD ), apr_pool); svn_err = svn_client_create_context( &context, svn_pool ); if(svn_err){a_logmsg("%s: svn error: %s",device_name,svn_err->message); a_debug_info2(DEBUGLVL5,"a_svn_diff: svn error: %s",svn_err->message); return -1;} svn_opt_revision_t pegrevision; pegrevision.kind = svn_opt_revision_unspecified; svn_opt_revision_t revision1; revision1.kind = svn_opt_revision_working; svn_opt_revision_t revision2; revision2.kind = svn_opt_revision_head; strcat(temp_svn_path,"/"); strcat(temp_svn_path,device_name); array = apr_array_make (apr_pool, 0, sizeof (const char *)); svn_err = svn_client_diff4(array, svn_path_canonicalize(temp_svn_path,apr_pool), &revision1, svn_path_canonicalize(full_device_svn_path,apr_pool), &revision2, NULL, svn_depth_empty, FALSE, TRUE, FALSE, APR_LOCALE_CHARSET, diff_outfile, diff_errfile, NULL, context, svn_pool); if(svn_err){ a_logmsg("%s: svn error: %s",device_name,svn_err->message); a_debug_info2(DEBUGLVL5,"a_svn_diff: svn error: %s",svn_err->message); return -1; } apr_file_close(diff_errfile); remove(svn_diff_errfname); apr_file_close(diff_outfile); if( (stat(svn_diff_outfname,&svn_diff_file_info)) == -1) a_debug_info2(DEBUGLVL5,"a_svn_diff: cannot stat %s!",svn_diff_outfname); svn_diff_file_size = (int)svn_diff_file_info.st_size; if((G_config_info.keep_changelog) && (svn_diff_file_size > 0)) if(!a_add_changelog_entry(svn_diff_outfname, svn_diff_file_size, device_name, configured_by)) { a_logmsg("a_svn_diff: %s: cannot write changelog entry!",device_name); a_debug_info2(DEBUGLVL5,"a_svn_diff: cannot write changelog entry!",device_name); } /* what we are returning here, is the length of a diff file */ /* if it is nonzero - revisions differ: */ remove(svn_diff_outfname); return svn_diff_file_size; }
/* fonction simulant la commande svn diff */ apr_array_header_t *svn_support_diff_call(char *rep_path, char *filename, int revision1, int revision2, apr_pool_t* subpool) { svn_error_t *err; apr_file_t *outfile; apr_file_t *errfile; apr_status_t rv; svn_opt_revision_t rev1; svn_opt_revision_t rev2; // -- Initialisation du tableau et du buffer de résultats -- apr_array_header_t *list_result = apr_array_make(subpool, 1, sizeof (const char *)); svn_stringbuf_t *res = svn_stringbuf_create("",subpool); // -- Initialisation des chemins des fichiers -- const svn_stringbuf_t *slash = svn_stringbuf_create("/",subpool); const svn_stringbuf_t *filepath = svn_stringbuf_create(filename,subpool); svn_stringbuf_t *path = svn_stringbuf_create(rep_path,subpool); if (strcmp(filename,"") != 0) { svn_stringbuf_appendstr(path,slash); svn_stringbuf_appendstr(path,filepath); } // -- Initialisation des revisions -- rev1.kind = rev2.kind = svn_opt_revision_number; rev1.value.number=revision1; rev2.value.number=revision2; // -- Initialisation des fichiers d'output -- if ((rv = apr_file_open_stdout(&outfile,subpool)) != APR_SUCCESS) { svn_pool_destroy(subpool); return NULL; } if ((rv = apr_file_open_stdout(&errfile,subpool)) != APR_SUCCESS) { svn_pool_destroy(subpool); return NULL; } const apr_array_header_t *diff_options = apr_array_make(subpool, 1, sizeof (const char *)); //apr_file_t *write_end; //apr_file_t *read_end; //apr_file_pipe_create(&write_end,&read_end,subpool); int tube[2]; pipe(tube); switch(fork()){ case -1: perror("fork"); svn_pool_destroy(subpool); return NULL; case 0: //apr_file_close(read_end); //apr_file_dup2(outfile,write_end,subpool); close(tube[0]); dup2(tube[1],STDOUT_FILENO); err = svn_client_diff4(diff_options, path->data, &rev1, path->data, &rev2, NULL, svn_depth_infinity, TRUE,// ignore_ancestry TRUE,// no_diff_deleted FALSE, // ignore_content_type SVN_APR_LOCALE_CHARSET, outfile, errfile, NULL, ctx, subpool); if (err) { svn_handle_error2 (err, stderr, FALSE, "svn_support_diff: "); svn_pool_destroy(subpool); return NULL; } exit(0); } //apr_file_close(write_end); close(tube[1]); int buf_size = 4096; char buf[buf_size]; int rc; const svn_stringbuf_t *tmp; while((rc=read(tube[0],buf,buf_size))>0){//(rv=apr_file_gets(buf,buf_size,read_end))){ //if(APR_STATUS_IS_EOF(rv)) //break; buf[rc]='\0'; tmp = svn_stringbuf_create(buf,subpool); svn_stringbuf_appendstr(res,tmp); //*(char **)apr_array_push(list_result) = buf; } wait(NULL); svn_cstring_split_endline_append(list_result,res->data,subpool); svn_pool_destroy(subpool); return list_result; }