Skip to content

Commit 28e56f0

Browse files
Refactor error handling and implement advanced diff
Updated error handling and added advanced diff functionality to compare commits and staged entries between two databases.
1 parent fc9cdf6 commit 28e56f0

File tree

1 file changed

+165
-12
lines changed

1 file changed

+165
-12
lines changed

code/logic/myshell.c

Lines changed: 165 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ fossil_bluecrab_myshell_error_t fossil_myshell_put(fossil_bluecrab_myshell_t *db
429429
}
430430
}
431431
if (!valid_type) {
432-
return FOSSIL_MYSHELL_ERROR_CONFIG_INVALID;
432+
return FOSSIL_MYSHELL_ERROR_INVALID_TYPE;
433433
}
434434

435435
uint64_t key_hash = myshell_hash64(key);
@@ -536,14 +536,16 @@ fossil_bluecrab_myshell_error_t fossil_myshell_get(
536536
} else {
537537
value_len = hash_comment - (eq + 1);
538538
}
539-
if (value_len >= out_size) value_len = out_size - 1;
539+
// Trim trailing whitespace/newline from value_len
540+
while (value_len > 0 && ((eq + 1)[value_len - 1] == '\n' || (eq + 1)[value_len - 1] == ' ')) {
541+
value_len--;
542+
}
543+
if (value_len >= out_size) {
544+
*eq = '='; // Restore
545+
return FOSSIL_MYSHELL_ERROR_BUFFER_TOO_SMALL;
546+
}
540547
strncpy(out_value, eq + 1, value_len);
541548
out_value[value_len] = '\0';
542-
// Trim trailing whitespace/newline
543-
size_t len = strlen(out_value);
544-
while (len > 0 && (out_value[len - 1] == '\n' || out_value[len - 1] == ' ')) {
545-
out_value[--len] = '\0';
546-
}
547549
*eq = '='; // Restore
548550
return FOSSIL_MYSHELL_ERROR_SUCCESS;
549551
}
@@ -554,14 +556,17 @@ fossil_bluecrab_myshell_error_t fossil_myshell_get(
554556
char *comment = strchr(eq + 1, '#');
555557
if (comment) {
556558
value_len = comment - (eq + 1);
557-
if (value_len >= out_size) value_len = out_size - 1;
559+
// Trim trailing whitespace/newline from value_len
560+
while (value_len > 0 && ((eq + 1)[value_len - 1] == '\n' || (eq + 1)[value_len - 1] == ' ')) {
561+
value_len--;
562+
}
563+
if (value_len >= out_size) {
564+
*eq = '='; // Restore
565+
return FOSSIL_MYSHELL_ERROR_BUFFER_TOO_SMALL;
566+
}
558567
}
559568
strncpy(out_value, eq + 1, value_len);
560569
out_value[value_len] = '\0';
561-
size_t len = strlen(out_value);
562-
while (len > 0 && (out_value[len - 1] == '\n' || out_value[len - 1] == ' ')) {
563-
out_value[--len] = '\0';
564-
}
565570
*eq = '='; // Restore
566571
return FOSSIL_MYSHELL_ERROR_SUCCESS;
567572
}
@@ -1607,3 +1612,151 @@ fossil_bluecrab_myshell_error_t fossil_myshell_check_integrity(fossil_bluecrab_m
16071612

16081613
return FOSSIL_MYSHELL_ERROR_SUCCESS;
16091614
}
1615+
1616+
fossil_bluecrab_myshell_error_t fossil_myshell_diff(
1617+
const fossil_bluecrab_myshell_t *db1,
1618+
const fossil_bluecrab_myshell_t *db2,
1619+
char *out_diff,
1620+
size_t out_size
1621+
) {
1622+
if (!db1 || !db2 || !db1->is_open || !db2->is_open || !out_diff || out_size == 0) {
1623+
return FOSSIL_MYSHELL_ERROR_INVALID_FILE;
1624+
}
1625+
1626+
// Advanced diff: compare all commits and staged entries, report adds/removes/changes.
1627+
fseek(db1->file, 0, SEEK_SET);
1628+
fseek(db2->file, 0, SEEK_SET);
1629+
1630+
char line1[1024], line2[1024];
1631+
size_t pos = 0;
1632+
1633+
// --- Collect commits from both files ---
1634+
typedef struct { char hash[17]; char line[1024]; } commit_t;
1635+
commit_t commits1[128], commits2[128];
1636+
size_t n1 = 0, n2 = 0;
1637+
1638+
while (fgets(line1, sizeof(line1), db1->file)) {
1639+
if (strncmp(line1, "#commit ", 8) == 0) {
1640+
char hash[17] = {0};
1641+
sscanf(line1, "#commit %16s", hash);
1642+
strncpy(commits1[n1].hash, hash, sizeof(commits1[n1].hash));
1643+
commits1[n1].hash[sizeof(commits1[n1].hash) - 1] = '\0';
1644+
strncpy(commits1[n1].line, line1, sizeof(line1));
1645+
n1++;
1646+
}
1647+
}
1648+
while (fgets(line2, sizeof(line2), db2->file)) {
1649+
if (strncmp(line2, "#commit ", 8) == 0) {
1650+
char hash[17] = {0};
1651+
strncpy(commits2[n2].hash, hash, 16);
1652+
commits2[n2].hash[16] = '\0';
1653+
strncpy(commits2[n2].line, line2, sizeof(line2));
1654+
n2++;
1655+
n2++;
1656+
}
1657+
}
1658+
1659+
// --- Compare commits ---
1660+
for (size_t i = 0; i < n1; ++i) {
1661+
bool found = false;
1662+
for (size_t j = 0; j < n2; ++j) {
1663+
if (strcmp(commits1[i].hash, commits2[j].hash) == 0) {
1664+
found = true;
1665+
if (strcmp(commits1[i].line, commits2[j].line) != 0) {
1666+
int n = snprintf(out_diff + pos, out_size - pos, "~ %s~ %s", commits1[i].line, commits2[j].line);
1667+
if (n < 0 || (size_t)n >= out_size - pos) return FOSSIL_MYSHELL_ERROR_CAPACITY_EXCEEDED;
1668+
pos += n;
1669+
}
1670+
break;
1671+
}
1672+
}
1673+
if (!found) {
1674+
int n = snprintf(out_diff + pos, out_size - pos, "- %s", commits1[i].line);
1675+
if (n < 0 || (size_t)n >= out_size - pos) return FOSSIL_MYSHELL_ERROR_CAPACITY_EXCEEDED;
1676+
pos += n;
1677+
}
1678+
}
1679+
for (size_t j = 0; j < n2; ++j) {
1680+
bool found = false;
1681+
for (size_t i = 0; i < n1; ++i) {
1682+
if (strcmp(commits2[j].hash, commits1[i].hash) == 0) {
1683+
found = true;
1684+
break;
1685+
}
1686+
}
1687+
if (!found) {
1688+
int n = snprintf(out_diff + pos, out_size - pos, "+ %s", commits2[j].line);
1689+
if (n < 0 || (size_t)n >= out_size - pos) return FOSSIL_MYSHELL_ERROR_CAPACITY_EXCEEDED;
1690+
pos += n;
1691+
}
1692+
}
1693+
1694+
// --- Collect staged entries from both files ---
1695+
typedef struct { char key[256]; char line[1024]; } stage_t;
1696+
stage_t stages1[128], stages2[128];
1697+
size_t s1 = 0, s2 = 0;
1698+
1699+
fseek(db1->file, 0, SEEK_SET);
1700+
while (fgets(line1, sizeof(line1), db1->file)) {
1701+
if (strncmp(line1, "#stage ", 7) == 0) {
1702+
char *eq = strchr(line1 + 7, '=');
1703+
if (eq) {
1704+
size_t klen = eq - (line1 + 7);
1705+
strncpy(stages1[s1].key, line1 + 7, klen);
1706+
stages1[s1].key[klen] = '\0';
1707+
strncpy(stages1[s1].line, line1, sizeof(line1));
1708+
s1++;
1709+
}
1710+
}
1711+
}
1712+
fseek(db2->file, 0, SEEK_SET);
1713+
while (fgets(line2, sizeof(line2), db2->file)) {
1714+
if (strncmp(line2, "#stage ", 7) == 0) {
1715+
char *eq = strchr(line2 + 7, '=');
1716+
if (eq) {
1717+
size_t klen = eq - (line2 + 7);
1718+
strncpy(stages2[s2].key, line2 + 7, klen);
1719+
stages2[s2].key[klen] = '\0';
1720+
strncpy(stages2[s2].line, line2, sizeof(line2));
1721+
s2++;
1722+
}
1723+
}
1724+
}
1725+
1726+
// --- Compare staged entries ---
1727+
for (size_t i = 0; i < s1; ++i) {
1728+
bool found = false;
1729+
for (size_t j = 0; j < s2; ++j) {
1730+
if (strcmp(stages1[i].key, stages2[j].key) == 0) {
1731+
found = true;
1732+
if (strcmp(stages1[i].line, stages2[j].line) != 0) {
1733+
int n = snprintf(out_diff + pos, out_size - pos, "~ %s~ %s", stages1[i].line, stages2[j].line);
1734+
if (n < 0 || (size_t)n >= out_size - pos) return FOSSIL_MYSHELL_ERROR_CAPACITY_EXCEEDED;
1735+
pos += n;
1736+
}
1737+
break;
1738+
}
1739+
}
1740+
if (!found) {
1741+
int n = snprintf(out_diff + pos, out_size - pos, "- %s", stages1[i].line);
1742+
if (n < 0 || (size_t)n >= out_size - pos) return FOSSIL_MYSHELL_ERROR_CAPACITY_EXCEEDED;
1743+
pos += n;
1744+
}
1745+
}
1746+
for (size_t j = 0; j < s2; ++j) {
1747+
bool found = false;
1748+
for (size_t i = 0; i < s1; ++i) {
1749+
if (strcmp(stages2[j].key, stages1[i].key) == 0) {
1750+
found = true;
1751+
break;
1752+
}
1753+
}
1754+
if (!found) {
1755+
int n = snprintf(out_diff + pos, out_size - pos, "+ %s", stages2[j].line);
1756+
if (n < 0 || (size_t)n >= out_size - pos) return FOSSIL_MYSHELL_ERROR_CAPACITY_EXCEEDED;
1757+
pos += n;
1758+
}
1759+
}
1760+
1761+
return FOSSIL_MYSHELL_ERROR_SUCCESS;
1762+
}

0 commit comments

Comments
 (0)