Fossil SCM

fossil-scm / src / diffcmd.c
Blame History Raw 185 lines
1
/*
2
** Copyright (c) 2007 D. Richard Hipp
3
**
4
** This program is free software; you can redistribute it and/or
5
** modify it under the terms of the Simplified BSD License (also
6
** known as the "2-Clause License" or "FreeBSD License".)
7
8
** This program is distributed in the hope that it will be useful,
9
** but without any warranty; without even the implied warranty of
10
** merchantability or fitness for a particular purpose.
11
**
12
** Author contact information:
13
** [email protected]
14
** http://www.hwaci.com/drh/
15
**
16
*******************************************************************************
17
**
18
** This file contains code used to implement the "diff" command
19
*/
20
#include "config.h"
21
#include "diffcmd.h"
22
#include <assert.h>
23
24
/* includes needed to catch interrupts */
25
#ifdef _WIN32
26
# include <windows.h>
27
#else
28
# include <signal.h>
29
#endif
30
31
/*
32
** Use the right null device for the platform.
33
*/
34
#if defined(_WIN32)
35
# define NULL_DEVICE "NUL"
36
#else
37
# define NULL_DEVICE "/dev/null"
38
#endif
39
40
/*
41
** Used when the name for the diff is unknown.
42
*/
43
#define DIFF_NO_NAME "(unknown)"
44
45
/*
46
** Use the "exec-rel-paths" setting and the --exec-abs-paths and
47
** --exec-rel-paths command line options to determine whether
48
** certain external commands are executed using relative paths.
49
*/
50
static int determine_exec_relative_option(int force){
51
static int relativePaths = -1;
52
if( force || relativePaths==-1 ){
53
int relPathOption = find_option("exec-rel-paths", 0, 0)!=0;
54
int absPathOption = find_option("exec-abs-paths", 0, 0)!=0;
55
#if defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
56
relativePaths = db_get_boolean("exec-rel-paths", 1);
57
#else
58
relativePaths = db_get_boolean("exec-rel-paths", 0);
59
#endif
60
if( relPathOption ){ relativePaths = 1; }
61
if( absPathOption ){ relativePaths = 0; }
62
}
63
return relativePaths;
64
}
65
66
#if INTERFACE
67
/*
68
** An array of FileDirList objects describe the files and directories listed
69
** on the command line of a "diff" command. Only those objects listed are
70
** actually diffed.
71
*/
72
struct FileDirList {
73
int nUsed; /* Number of times each entry is used */
74
int nName; /* Length of the entry */
75
char *zName; /* Text of the entry */
76
};
77
#endif
78
79
/*
80
** Return true if zFile is a file named on the azInclude[] list or is
81
** a file in a directory named on the azInclude[] list.
82
**
83
** if azInclude is NULL, then always include zFile.
84
*/
85
static int file_dir_match(FileDirList *p, const char *zFile){
86
if( p==0 || strcmp(p->zName,".")==0 ) return 1;
87
if( filenames_are_case_sensitive() ){
88
while( p->zName ){
89
if( strcmp(zFile, p->zName)==0
90
|| (strncmp(zFile, p->zName, p->nName)==0
91
&& zFile[p->nName]=='/')
92
){
93
break;
94
}
95
p++;
96
}
97
}else{
98
while( p->zName ){
99
if( fossil_stricmp(zFile, p->zName)==0
100
|| (fossil_strnicmp(zFile, p->zName, p->nName)==0
101
&& zFile[p->nName]=='/')
102
){
103
break;
104
}
105
p++;
106
}
107
}
108
if( p->zName ){
109
p->nUsed++;
110
return 1;
111
}
112
return 0;
113
}
114
115
/*
116
** Print details about the compared versions - possibly the working directory
117
** or the undo buffer. For check-ins, show hash and commit time.
118
**
119
** This is intended primarily to go into the "header garbage" that is ignored
120
** by patch(1).
121
**
122
** zFrom and zTo are interpreted as symbolic version names, unless they
123
** start with '(', in which case they are printed directly.
124
*/
125
void diff_print_versions(const char *zFrom, const char *zTo, DiffConfig *pCfg){
126
if( (pCfg->diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF|DIFF_NUMSTAT|
127
DIFF_HTML|DIFF_WEBPAGE|DIFF_BROWSER|DIFF_JSON|DIFF_TCL))==0 ){
128
fossil_print("Fossil-Diff-From: %s\n",
129
zFrom[0]=='(' ? zFrom : mprintf("%S %s",
130
rid_to_uuid(symbolic_name_to_rid(zFrom, "ci")),
131
db_text("","SELECT datetime(%f)||' UTC'",
132
symbolic_name_to_mtime(zFrom, 0, 0))));
133
fossil_print("Fossil-Diff-To: %s\n",
134
zTo[0]=='(' ? zTo : mprintf("%S %s",
135
rid_to_uuid(symbolic_name_to_rid(zTo, "ci")),
136
db_text("","SELECT datetime(%f)||' UTC'",
137
symbolic_name_to_mtime(zTo, 0, 1))));
138
fossil_print("%.66c\n", '-');
139
}
140
}
141
142
/*
143
** Print the "Index:" message that patches wants to see at the top of a diff.
144
*/
145
void diff_print_index(const char *zFile, DiffConfig *pCfg, Blob *pOut){
146
if( (pCfg->diffFlags &
147
(DIFF_SIDEBYSIDE|DIFF_BRIEF|DIFF_NUMSTAT|DIFF_JSON|
148
DIFF_WEBPAGE|DIFF_TCL))==0
149
){
150
blob_appendf(pOut, "Index: %s\n%.66c\n", zFile, '=');
151
}
152
}
153
154
/*
155
** Print the +++/--- filename lines or whatever filename information
156
** is appropriate for the output format.
157
**
158
*/
159
void diff_print_filenames(
160
const char *zLeft, /* Name of the left file */
161
const char *zRight, /* Name of the right file */
162
DiffConfig *pCfg, /* Diff configuration */
163
Blob *pOut /* Write to this blob, or stdout of this is NULL */
164
){
165
u64 diffFlags = pCfg->diffFlags;
166
/* Standardize on /dev/null, regardless of platform. */
167
if( pCfg->diffFlags & DIFF_FILE_ADDED ) zLeft = "/dev/null";
168
if( pCfg->diffFlags & DIFF_FILE_DELETED ) zRight = "/dev/null";
169
if( pCfg->azLabel[0] ) zLeft = pCfg->azLabel[0];
170
if( pCfg->azLabel[1] ) zRight = pCfg->azLabel[1];
171
if( diffFlags & (DIFF_BRIEF|DIFF_RAW) ){
172
/* no-op */
173
}else if( diffFlags & DIFF_DEBUG ){
174
blob_appendf(pOut, "FILE-LEFT %s\nFILE-RIGHT %s\n", zLeft, zRight);
175
}else if( diffFlags & DIFF_WEBPAGE ){
176
if( fossil_strcmp(zLeft,zRight)==0 ){
177
blob_appendf(pOut,"<h1>%h</h1>\n", zLeft);
178
}else{
179
blob_appendf(pOut,"<h1>%h &lrarr; %h</h1>\n", zLeft, zRi {
180
@ font-size: 150%;
181
@ }
182
@ table.diff {
183
@ width: 100%;
184
@ bo ){
185
blob_append line-height: inhe

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button