Skip to content

Commit 81b5ac2

Browse files
Added two checks when loading a file to determine if two cells are
the same: (1) If the inodes of the filename are the same, then the cells are the same. This avoids treating symbolic links as different paths with different files; (2) If both layouts are in git repositories and the git repository commit hashes are the same, then the cells are considered to be the same. This allows projects to be cloned into other projects as dependencies and used in multiple places without magic treating them as different layouts.
1 parent e9db9ec commit 81b5ac2

File tree

2 files changed

+118
-1
lines changed

2 files changed

+118
-1
lines changed

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8.3.485
1+
8.3.486

database/DBio.c

+117
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
2828
#include <errno.h>
2929
#include <sys/types.h>
3030
#include <sys/file.h>
31+
#include <sys/stat.h>
32+
#include <sys/wait.h>
3133

3234
#ifdef HAVE_DIRENT_H
3335
#include <dirent.h>
@@ -1973,6 +1975,121 @@ dbReadUse(cellDef, line, len, f, scalen, scaled, dereference, dbUseTable)
19731975
}
19741976
else if (!strcmp(cwddir, pathptr)) pathOK = TRUE;
19751977

1978+
/* Apply same check as done in DBWprocs, which is to check the
1979+
* inode of the two files and declare the path okay if they are
1980+
* the same. This avoids conflicts in files that are referenced
1981+
* from two different places via different relative paths, or
1982+
* through symbolic links.
1983+
*/
1984+
1985+
if ((pathOK == FALSE) && strcmp(subCellDef->cd_file, pathptr)
1986+
&& (dereference == FALSE) && (firstUse == TRUE))
1987+
{
1988+
struct stat statbuf;
1989+
ino_t inode;
1990+
1991+
if (stat(subCellDef->cd_file, &statbuf) == 0)
1992+
{
1993+
inode = statbuf.st_ino;
1994+
1995+
if (stat(pathptr, &statbuf) == 0)
1996+
{
1997+
if (inode == statbuf.st_ino)
1998+
pathOK = TRUE;
1999+
}
2000+
}
2001+
}
2002+
2003+
if ((pathOK == FALSE) && strcmp(subCellDef->cd_file, pathptr)
2004+
&& (dereference == FALSE) && (firstUse == TRUE))
2005+
{
2006+
/* See if both paths are inside a git repository, and both
2007+
* git repositories have the same commit hash. Then the
2008+
* two layouts can be considered equivalent. If the "git"
2009+
* command fails for any reason, then ignore the error and
2010+
* continue.
2011+
*/
2012+
char *sl1ptr, *sl2ptr;
2013+
int link[2], nbytes, status;
2014+
pid_t pid;
2015+
char githash1[128];
2016+
char githash2[128];
2017+
char argstr[1024];
2018+
2019+
githash1[0] = '\0';
2020+
2021+
/* Remove the file component */
2022+
sl1ptr = strrchr(pathptr, '/');
2023+
if (sl1ptr != NULL) *sl1ptr = '\0';
2024+
2025+
/* Check first file for a git hash */
2026+
if (pipe(link) != -1)
2027+
{
2028+
FORK(pid);
2029+
if (pid == 0)
2030+
{
2031+
dup2(link[1], STDOUT_FILENO);
2032+
close(link[0]);
2033+
close(link[1]);
2034+
sprintf(argstr, "-C %s", pathptr);
2035+
execlp("git", argstr, "rev-parse", "HEAD", NULL);
2036+
_exit(122); /* see vfork man page for reason for _exit() */
2037+
}
2038+
else
2039+
{
2040+
close(link[1]);
2041+
nbytes = read(link[0], githash1, sizeof(githash1));
2042+
waitpid(pid, &status, 0);
2043+
}
2044+
}
2045+
2046+
if (sl1ptr != NULL) *sl1ptr = '/';
2047+
2048+
if (githash1[0] != '\0')
2049+
{
2050+
/* Check the second repository */
2051+
2052+
/* Remove the file component */
2053+
sl2ptr = strrchr(subCellDef->cd_file, '/');
2054+
if (sl2ptr != NULL) *sl2ptr = '\0';
2055+
2056+
/* Check first file for a git hash */
2057+
if (pipe(link) != -1)
2058+
{
2059+
FORK(pid);
2060+
if (pid == 0)
2061+
{
2062+
dup2(link[1], STDOUT_FILENO);
2063+
close(link[0]);
2064+
close(link[1]);
2065+
sprintf(argstr, "-C %s", subCellDef->cd_file);
2066+
execlp("git", argstr, "rev-parse", "HEAD", NULL);
2067+
_exit(123); /* see vfork man page for reason for _exit() */
2068+
}
2069+
else
2070+
{
2071+
close(link[1]);
2072+
nbytes = read(link[0], githash2, sizeof(githash2));
2073+
waitpid(pid, &status, 0);
2074+
}
2075+
}
2076+
2077+
if (sl2ptr != NULL) *sl2ptr = '/';
2078+
2079+
if (githash2[0] != '\0')
2080+
{
2081+
/* Check if the repositories have the same hash */
2082+
if (!strcmp(githash1, githash2))
2083+
{
2084+
TxPrintf("Cells %s in %s and %s have matching git repository"
2085+
" commits and can be considered equivalent.\n",
2086+
slashptr + 1, subCellDef->cd_file, pathptr);
2087+
pathOK = TRUE;
2088+
}
2089+
}
2090+
}
2091+
}
2092+
19762093
if ((pathOK == FALSE) && strcmp(subCellDef->cd_file, pathptr)
19772094
&& (dereference == FALSE) && (firstUse == TRUE))
19782095
{

0 commit comments

Comments
 (0)