Git development
 help / color / mirror / Atom feed
* cg-add and update-cache add fails
From: Rhys Hardwick @ 2005-04-26 16:35 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 925 bytes --]

Hey there,

I posted a little while ago about this, but thought I would collate all my 
findings.  I am very lost.  Trying to add files to the repository does not 
seem to work, no matter which git repository I try.  Creating new trees and 
updating current trees, as well as removing files is not a problem.  All 
other areas of git seem to work perfectly.  I am currently using cogito-0.8.  
This error started to occur in pasky-0.63.

Here is the error I get:

rhys@metatron:~/repo/learning.repo$ cg-add w1p4d1.c
fatal: Unable to add w1p4d1.c to database
rhys@metatron:~/repo/learning.repo$ update-cache --add w1p4d1.c
fatal: Unable to add w1p4d1.c to database

All the files under the .git folder appear to be owned by me, and are 
read-writable.  The disk is not full.  

I have attached the output from strace and ltrace.

If anyone could shed any light on why this might be happening, I would be very 
grateful.

Rhys

[-- Attachment #2: strace and ltrace --]
[-- Type: text/plain, Size: 20437 bytes --]

rhys@metatron:~/repo/learning.repo$ strace cg-add w1d4p1.c
execve("/home/rhys/bin/cg-add", ["cg-add", "w1d4p1.c"], [/* 37 vars */]) = 0
uname({sys="Linux", node="metatron", ...}) = 0
brk(0)                                  = 0x804c000
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe9000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=78602, ...}) = 0
old_mmap(NULL, 78602, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fd5000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/tls/libc.so.6", O_RDONLY)    = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0`Z\1\000"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=1254468, ...}) = 0
old_mmap(NULL, 1264780, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xb7ea0000
old_mmap(0xb7fca000, 36864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x129000) = 0xb7fca000
old_mmap(0xb7fd3000, 7308, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fd3000
close(3)                                = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e9f000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7e9f460, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0xb7fd5000, 78602)               = 0
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=290448, ...}) = 0
mmap2(NULL, 290448, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7e58000
close(3)                                = 0
brk(0)                                  = 0x804c000
brk(0x806d000)                          = 0x806d000
brk(0)                                  = 0x806d000
execve("/usr/local/bin/bash", ["bash", "/home/rhys/bin/cg-add", "w1d4p1.c"], [/* 37 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/bin/bash", ["bash", "/home/rhys/bin/cg-add", "w1d4p1.c"], [/* 37 vars */]) = -1 ENOENT (No such file or directory)
execve("/bin/bash", ["bash", "/home/rhys/bin/cg-add", "w1d4p1.c"], [/* 37 vars */]) = 0
uname({sys="Linux", node="metatron", ...}) = 0
brk(0)                                  = 0x80f1000
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe9000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=78602, ...}) = 0
old_mmap(NULL, 78602, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fd5000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/libncurses.so.5", O_RDONLY)  = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\342"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=252592, ...}) = 0
old_mmap(NULL, 257868, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xb7f96000
old_mmap(0xb7fcc000, 36864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x35000) = 0xb7fcc000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/tls/libdl.so.2", O_RDONLY)   = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\32"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=9872, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f95000
old_mmap(NULL, 8632, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xb7f92000
old_mmap(0xb7f94000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x2000) = 0xb7f94000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/tls/libc.so.6", O_RDONLY)    = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0`Z\1\000"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=1254468, ...}) = 0
old_mmap(NULL, 1264780, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xb7e5d000
old_mmap(0xb7f87000, 36864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x129000) = 0xb7f87000
old_mmap(0xb7f90000, 7308, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f90000
close(3)                                = 0
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7f95b80, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0xb7fd5000, 78602)               = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
open("/dev/tty", O_RDWR|O_NONBLOCK|O_LARGEFILE) = 3
close(3)                                = 0
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=290448, ...}) = 0
mmap2(NULL, 290448, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7e16000
close(3)                                = 0
brk(0)                                  = 0x80f1000
brk(0)                                  = 0x80f1000
brk(0x80f2000)                          = 0x80f2000
brk(0)                                  = 0x80f2000
brk(0x80f3000)                          = 0x80f3000
brk(0)                                  = 0x80f3000
brk(0x80f4000)                          = 0x80f4000
getuid32()                              = 1000
getgid32()                              = 1000
geteuid32()                             = 1000
getegid32()                             = 1000
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
time(NULL)                              = 1114533106
brk(0)                                  = 0x80f4000
brk(0x80f5000)                          = 0x80f5000
open("/etc/mtab", O_RDONLY)             = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=381, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e15000
read(3, "/dev/hda7 / ext3 rw,errors=remou"..., 4096) = 381
close(3)                                = 0
munmap(0xb7e15000, 4096)                = 0
open("/proc/meminfo", O_RDONLY)         = 3
fstat64(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e15000
read(3, "MemTotal:       906680 kB\nMemFre"..., 1024) = 598
close(3)                                = 0
munmap(0xb7e15000, 4096)                = 0
brk(0)                                  = 0x80f5000
brk(0x80f6000)                          = 0x80f6000
rt_sigaction(SIGCHLD, {SIG_DFL}, {SIG_DFL}, 8) = 0
rt_sigaction(SIGCHLD, {SIG_DFL}, {SIG_DFL}, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL}, {SIG_DFL}, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL}, {SIG_DFL}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL}, {SIG_DFL}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL}, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigaction(SIGQUIT, {SIG_IGN}, {SIG_DFL}, 8) = 0
uname({sys="Linux", node="metatron", ...}) = 0
brk(0)                                  = 0x80f6000
brk(0x80f7000)                          = 0x80f7000
stat64("/home/rhys/repo/learning.repo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getpid()                                = 9873
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
brk(0)                                  = 0x80f7000
brk(0x80f8000)                          = 0x80f8000
open("/usr/lib/gconv/gconv-modules", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=45278, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e15000
read(3, "# GNU libc iconv configuration.\n"..., 4096) = 4096
brk(0)                                  = 0x80f8000
brk(0x80f9000)                          = 0x80f9000
read(3, ".B1.002//\nalias\tJS//\t\t\tJUS_I.B1."..., 4096) = 4096
brk(0)                                  = 0x80f9000
brk(0x80fa000)                          = 0x80fa000
brk(0)                                  = 0x80fa000
brk(0x80fb000)                          = 0x80fb000
brk(0)                                  = 0x80fb000
brk(0x80fc000)                          = 0x80fc000
read(3, "859-3\t1\nmodule\tINTERNAL\t\tISO-885"..., 4096) = 4096
brk(0)                                  = 0x80fc000
brk(0x80fd000)                          = 0x80fd000
brk(0)                                  = 0x80fd000
brk(0x80fe000)                          = 0x80fe000
brk(0)                                  = 0x80fe000
brk(0x80ff000)                          = 0x80ff000
read(3, "9-14//\nalias\tLATIN8//\t\tISO-8859-"..., 4096) = 4096
brk(0)                                  = 0x80ff000
brk(0x8100000)                          = 0x8100000
brk(0)                                  = 0x8100000
brk(0x8101000)                          = 0x8101000
brk(0)                                  = 0x8101000
brk(0x8102000)                          = 0x8102000
read(3, "CSEBCDICES//\t\tEBCDIC-ES//\nalias\t"..., 4096) = 4096
brk(0)                                  = 0x8102000
brk(0x8103000)                          = 0x8103000
brk(0)                                  = 0x8103000
brk(0x8104000)                          = 0x8104000
read(3, "IBM284//\nalias\tEBCDIC-CP-ES//\t\tI"..., 4096) = 4096
brk(0)                                  = 0x8104000
brk(0x8105000)                          = 0x8105000
brk(0)                                  = 0x8105000
brk(0x8106000)                          = 0x8106000
brk(0)                                  = 0x8106000
brk(0x8107000)                          = 0x8107000
read(3, "ias\t864//\t\t\tIBM864//\nalias\tCSIBM"..., 4096) = 4096
brk(0)                                  = 0x8107000
brk(0x8108000)                          = 0x8108000
brk(0)                                  = 0x8108000
brk(0x8109000)                          = 0x8109000
brk(0)                                  = 0x8109000
brk(0x810a000)                          = 0x810a000
read(3, "\tIBM937\t\t1\nmodule\tINTERNAL\t\tIBM9"..., 4096) = 4096
brk(0)                                  = 0x810a000
brk(0x810b000)                          = 0x810b000
brk(0)                                  = 0x810b000
brk(0x810c000)                          = 0x810c000
brk(0)                                  = 0x810c000
brk(0x810d000)                          = 0x810d000
read(3, "UC-JP//\nmodule\tEUC-JP//\t\tINTERNA"..., 4096) = 4096
brk(0)                                  = 0x810d000
brk(0x810e000)                          = 0x810e000
brk(0)                                  = 0x810e000
brk(0x810f000)                          = 0x810f000
brk(0)                                  = 0x810f000
brk(0x8110000)                          = 0x8110000
read(3, "143IECP271//\tIEC_P27-1//\nalias\tI"..., 4096) = 4096
brk(0)                                  = 0x8110000
brk(0x8111000)                          = 0x8111000
brk(0)                                  = 0x8111000
brk(0x8112000)                          = 0x8112000
read(3, "\nmodule\tINTERNAL\t\tISO_10367-BOX/"..., 4096) = 4096
brk(0)                                  = 0x8112000
brk(0x8113000)                          = 0x8113000
brk(0)                                  = 0x8113000
brk(0x8114000)                          = 0x8114000
brk(0)                                  = 0x8114000
brk(0x8115000)                          = 0x8115000
read(3, "\t\tto\t\t\tmodule\t\tcost\nmodule\tShift"..., 4096) = 222
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb7e15000, 4096)                = 0
brk(0)                                  = 0x8115000
brk(0x8116000)                          = 0x8116000
open("/usr/lib/gconv/ISO8859-1.so", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0`\6\0\000"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=5920, ...}) = 0
brk(0)                                  = 0x8116000
brk(0x8117000)                          = 0x8117000
old_mmap(NULL, 8860, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xb7e13000
old_mmap(0xb7e15000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1000) = 0xb7e15000
close(3)                                = 0
getppid()                               = 9872
stat64(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/usr/local/bin/bash", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/bash", 0xbffff490)     = -1 ENOENT (No such file or directory)
stat64("/bin/bash", {st_mode=S_IFREG|0755, st_size=667180, ...}) = 0
getgroups32(32, [20, 24, 25, 29, 33, 44, 1000]) = 7
stat64("/bin/bash", {st_mode=S_IFREG|0755, st_size=667180, ...}) = 0
getpgrp()                               = 9872
rt_sigaction(SIGCHLD, {0x807ac80, [], 0}, {SIG_DFL}, 8) = 0
brk(0)                                  = 0x8117000
brk(0x8118000)                          = 0x8118000
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
open("/home/rhys/bin/cg-add", O_RDONLY|O_LARGEFILE) = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbffff608) = -1 ENOTTY (Inappropriate ioctl for device)
_llseek(3, 0, [0], SEEK_CUR)            = 0
read(3, "#!/usr/bin/env bash\n#\n# Add new "..., 80) = 80
_llseek(3, 0, [0], SEEK_SET)            = 0
getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=1024}) = 0
dup2(3, 255)                            = 255
close(3)                                = 0
fcntl64(255, F_SETFD, FD_CLOEXEC)       = 0
fcntl64(255, F_GETFL)                   = 0x8000 (flags O_RDONLY|O_LARGEFILE)
fstat64(255, {st_mode=S_IFREG|0755, st_size=300, ...}) = 0
_llseek(255, 0, [0], SEEK_CUR)          = 0
brk(0)                                  = 0x8118000
brk(0x8119000)                          = 0x8119000
brk(0)                                  = 0x8119000
brk(0x811a000)                          = 0x811a000
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(255, "#!/usr/bin/env bash\n#\n# Add new "..., 300) = 300
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
stat64(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/usr/local/bin/cg-Xlib", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/cg-Xlib", 0xbffff490)  = -1 ENOENT (No such file or directory)
stat64("/bin/cg-Xlib", 0xbffff490)      = -1 ENOENT (No such file or directory)
stat64("/usr/bin/X11/cg-Xlib", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/usr/games/cg-Xlib", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/home/rhys/bin/cg-Xlib", {st_mode=S_IFREG|0755, st_size=835, ...}) = 0
stat64("/home/rhys/bin/cg-Xlib", {st_mode=S_IFREG|0755, st_size=835, ...}) = 0
open("/home/rhys/bin/cg-Xlib", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0755, st_size=835, ...}) = 0
read(3, "#!/usr/bin/env bash\n#\n# Common c"..., 835) = 835
close(3)                                = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
brk(0)                                  = 0x811a000
brk(0x811b000)                          = 0x811b000
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
stat64(".git", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
stat64(".git/remotes", 0xbffff070)      = -1 ENOENT (No such file or directory)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
stat64(".git", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
stat64(".git/refs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
stat64(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/usr/local/bin/update-cache", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/update-cache", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/bin/update-cache", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/X11/update-cache", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/usr/games/update-cache", 0xbffff490) = -1 ENOENT (No such file or directory)
stat64("/home/rhys/bin/update-cache", {st_mode=S_IFREG|0755, st_size=91464, ...}) = 0
stat64("/home/rhys/bin/update-cache", {st_mode=S_IFREG|0755, st_size=91464, ...}) = 0
brk(0)                                  = 0x811b000
brk(0x811c000)                          = 0x811c000
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
clone(fatal: Unable to add w1d4p1.c to database
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7f95bc8) = 9874
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
waitpid(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 1}], WNOHANG) = 9874
waitpid(-1, 0xbffff164, WNOHANG)        = -1 ECHILD (No child processes)
sigreturn()                             = ? (mask now [])
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x8079bd0, [], 0}, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL}, {0x8079bd0, [], 0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(255, "", 300)                      = 0
exit_group(1)                           = ?

========================================================================================

rhys@metatron:~/repo/learning.repo$ ltrace update-cache --add w1d4p1.c
__libc_start_main(0x80496b0, 3, 0xbffff854, 0x804ae20, 0x804ae80 <unfinished ...>
getenv("GIT_INDEX_FILE")                         = NULL
snprintf(".git/index.lock", 4097, "%s.lock", ".git/index") = 15
open(".git/index.lock", 194, 0600)               = 3
__cxa_atexit(0x8049690, 0, 0, 0xb7f8de80, 0xbffff7c8) = 0
__errno_location()                               = 0xb7d59280
getenv("SHA1_FILE_DIRECTORY")                    = NULL
access(".git/objects", 1)                        = 0
getenv("GIT_INDEX_FILE")                         = NULL
open(".git/index", 0, 026777021220)              = 4
__fxstat(3, 4, 0xbffff710)                       = 0
__errno_location()                               = 0xb7d59280
mmap(0, 176, 1, 2, 4)                            = 0xb7fe8000
close(4)                                         = 0
SHA1_Init(0xbffff660, 0xb7e67bc8, 0xb7fc2290, 0x804870e, 96) = 1
SHA1_Update(0xbffff660, 0xb7fe8000, 156, 0x804870e, 96) = 1
SHA1_Final(0xbffff640, 0xbffff660, 156, 0x804870e, 96) = 1
calloc(27, 4)                                    = 0x8050008
open("w1d4p1.c", 0, 044653)                      = -1
__errno_location()                               = 0xb7d59280
fputs("fatal: ", 0xb7f86f60fatal: )                     = 1
vfprintf(0xb7f86f60, "Unable to add %s to database", 0xbffff794Unable to add w1d4p1.c to database) = 34
fputc('\n', 0xb7f86f60
)                          = 10
exit(1 <unfinished ...>
unlink(".git/index.lock")                        = 0
+++ exited (status 1) +++
rhys@metatron:~/repo/learning.repo$      

^ permalink raw reply

* Re: Mercurial 0.3 vs git benchmarks
From: Magnus Damm @ 2005-04-26 16:23 UTC (permalink / raw)
  To: Chris Mason; +Cc: Linus Torvalds, Mike Taht, Matt Mackall, linux-kernel, git
In-Reply-To: <200504261138.46339.mason@suse.com>

On 4/26/05, Chris Mason <mason@suse.com> wrote:
> On Tuesday 26 April 2005 11:09, Magnus Damm wrote:
> > On 4/26/05, Chris Mason <mason@suse.com> wrote:
> > > This agrees with my tests here, the time to apply patches is somewhat
> > > disk bound, even for the small 100 or 200 patch series.  The io should be
> > > coming from data=ordered, since the commits are still every 5 seconds or
> > > so.
> >
> > Yes, as long as you apply the patches to disk that is. I've hacked up
> > a small backend tool that applies patches to files kept in memory and
> > uses a modifed rabin-karp search to match hunks. So you basically read
> > once and write once per file instead of moving data around for each
> > applied patch. But it needs two passes.
> >
> > And no, the source code for the entire Linux kernel is not kept in
> > memory - you need a smart frontend to manage the file cache. Drop me a
> > line if you are interested.
> 
> Sorry, you've lost me.  Right now the cycle goes like this:

Ehrm, maybe I'm way off. =)

> 1) patch reads patch file, reads source file, writes source file
> 2) update-cache reads source file, writes git file

Ok.

> Which of those writes are you avoiding?  We have a smart way to manage the
> cache already for the source files...the vm does pretty well.  There's
> nothing to manage for the git files.  For the apply a bunch of patches
> workload, they are write once, read never (except for the index).

Well, maybe I misunderstood everything, but I thought you were
applying a lot of patches and complained that it took a lot of time
due to the data order.

When I applied a lot of patches to the kernel recently the cpu load
dropped to zero after a while and the HD worked hard a sec or two and
then things came back again. My primitive guess is that it was because
the ext3 journal became full. To workaround this fact I started
hacking on this in-memory patcher.

In the cycle above, I'm trying to speed up step 1:
If the patch modifies each source file multiple times (either using
multiple hunks or multiple ---/+++) then the lines below the hunk in
the source file will be moved multiple times. And if the source file
is written to disk after each hunk or ---/+++ is applied then this
will generate a lot of writes that can be avoided if the entire patch
procedure is broken down into a first pass that analyzes the patches
and a second pass that applies the patches and keeps source files in
memory.

But my rather trivial observation above is of course only suitable if
you have a lot of patches that should be applied and you are only
interested in the final version of the patched source files. If you
apply one patch at a time and import each source file as a new
revision then my little hack is probably not for you.

/ magnus

^ permalink raw reply

* Re: Mercurial 0.3 vs git benchmarks
From: Bill Davidsen @ 2005-04-26 16:11 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Mike Taht, Matt Mackall, linux-kernel, git
In-Reply-To: <Pine.LNX.4.58.0504251938210.18901@ppc970.osdl.org>

[-- Attachment #1: Type: text/plain, Size: 1248 bytes --]

Linus Torvalds wrote:
> 
> On Mon, 25 Apr 2005, Mike Taht wrote:
> 
>>One difference is probably - mercurial appears to be using zlib's 
>>*default* compression of 6....
>>
>>using zlib compression of 9 really impacts git...
> 
> 
> I agree that it will hurt for big changes, but since I really do believe 
> that most changes are just a couple of files, I don't believe it matters 
> for those. 
> 
> I forget what the exact numbers were, but I did some timings on plain
> "gzip", and it basically said that doing gzip on a medium-sized file was
> not that different for -6 and -9. Why? Because most of the overhead was
> elsewhere ;)

Certainly not different in the overall numbers, but after trying gzip on 
a bunch of various source files on 32 bit CPUs, from P-II to Xeon, it 
looks as if after 7 the cpu jumps about 40% to 8, and another 30% to 9. 
Neither 8 nor 9 give any significant size improvement (< 2%).

Again, this is 32 bit CPU and just the gzip component, reading from 
stdin and writing to stdout which I hope gets directory operations out 
of the time measure.

Sample attached.

-- 
    -bill davidsen (davidsen@tmr.com)
"The secret to procrastination is to put things off until the
  last possible moment - but no longer"  -me

[-- Attachment #2: ziptime.log --]
[-- Type: text/plain, Size: 1037 bytes --]

Comp level 1

real	0m1.972s
user	0m1.790s
sys	0m0.098s
-rw-r--r--    1 davidsen  1792050 Apr 26 11:56 dummy.tar.gz
Comp level 2

real	0m2.021s
user	0m1.858s
sys	0m0.097s
-rw-r--r--    1 davidsen  1737227 Apr 26 11:56 dummy.tar.gz
Comp level 3

real	0m2.296s
user	0m2.124s
sys	0m0.095s
-rw-r--r--    1 davidsen  1697644 Apr 26 11:56 dummy.tar.gz
Comp level 4

real	0m2.604s
user	0m2.423s
sys	0m0.099s
-rw-r--r--    1 davidsen  1593207 Apr 26 11:56 dummy.tar.gz
Comp level 5

real	0m3.181s
user	0m3.003s
sys	0m0.087s
-rw-r--r--    1 davidsen  1549050 Apr 26 11:56 dummy.tar.gz
Comp level 6

real	0m4.185s
user	0m3.965s
sys	0m0.089s
-rw-r--r--    1 davidsen  1531866 Apr 26 11:56 dummy.tar.gz
Comp level 7

real	0m4.889s
user	0m4.642s
sys	0m0.096s
-rw-r--r--    1 davidsen  1524350 Apr 26 11:57 dummy.tar.gz
Comp level 8

real	0m7.836s
user	0m7.532s
sys	0m0.085s
-rw-r--r--    1 davidsen  1513763 Apr 26 11:57 dummy.tar.gz
Comp level 9

real	0m11.020s
user	0m10.616s
sys	0m0.092s
-rw-r--r--    1 davidsen  1511970 Apr 26 11:57 dummy.tar.gz

^ permalink raw reply

* [PATCH] Cogito chicken-and-egg problem
From: Pavel Roskin @ 2005-04-26 16:06 UTC (permalink / raw)
  To: git

Hello!

My patch for Makefile was misapplied, so installed commit-id is still
needed for "make" to succeed.

Shell commands are processed by make before being passed to the shell,
and $(...) is expanded by make before new PATH is set, as it is done in
the current Makefile.

Also, the dependency on commit-id was dropped from my patch for some
reason.  I believe it's still needed.  Also, we need a dependency on
cat-file, which is used by commit-id internally.

Signed-off-by: Pavel Roskin <proski@gnu.org>

Index: Makefile
===================================================================
--- f262000f302b749e485f5eb971e6aabefbb85680/Makefile  (mode:100644 sha1:4f01bbbbb3fd0e53e9ce968f167b6dae68fcfa92)
+++ uncommitted/Makefile  (mode:100644)
@@ -87,11 +87,11 @@
 http-pull: LIBS += -lcurl
 
 
-cg-version: $(VERSION)
+cg-version: $(VERSION) commit-id cat-file
 	@echo Generating cg-version...
 	@rm -f $@
 	@echo "#!/bin/sh" > $@
-	@PATH=.:$(PATH) echo "echo \"$(shell cat $(VERSION)) ($(shell commit-id))\"" >> $@
+	@echo "echo \"$(shell cat $(VERSION)) ($(shell PATH=.:$(PATH) ./commit-id))\"" >> $@
 	@chmod +x $@
 
 install: $(PROG) $(SCRIPTS) $(SCRIPT) $(GEN_SCRIPT)


-- 
Regards,
Pavel Roskin


^ permalink raw reply

* Re: : Networking
From: Daniel Barkalow @ 2005-04-26 15:40 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, David S. Miller, git
In-Reply-To: <Pine.LNX.4.58.0504260746320.18901@ppc970.osdl.org>

On Tue, 26 Apr 2005, Linus Torvalds wrote:

> On Tue, 26 Apr 2005, Andrew Morton wrote:
> > 
> 
> The only thing you should be a bit careful about is to remember what the 
> "heads" at different points were. In particular, you want to remember 
> where you merged with me last was. I've started tagging my releases with 
> the git tag facility (_not_ the pasky one, but I think pasky will start 
> picking up on that soon enough), so finding a specific release will be 
> easy, but if you ever do a non-release merge you'll just have to tag it 
> yourself.

Your tag system is in the "cogito-0.8" release, plus a pasky-style way of
keeping track of what tags you have in your repository.

> > d) To generate davem's tree (patch against linus's current tree (ie: patch
> >    against 2.6.12-rc3+linus.patch)):
> > 
> > 	git pull git-net
> 
> Yes. This should have merged the two (assuming "git pull" does what I 
> think it does).

I think git pull only downloads the contents of the repo and saves the new
head in a separate file. You're left to do the merge yourself, in case
what you actually wanted to do was just read the patches in the remote
repo without merging them.

You probably need a "git merge git-net" here, and things will be in the
state that Linus expects.

	-Daniel
*This .sig left intentionally blank*


^ permalink raw reply

* Re: Mercurial 0.3 vs git benchmarks
From: Chris Mason @ 2005-04-26 15:38 UTC (permalink / raw)
  To: Magnus Damm; +Cc: Linus Torvalds, Mike Taht, Matt Mackall, linux-kernel, git
In-Reply-To: <aec7e5c305042608095731d571@mail.gmail.com>

On Tuesday 26 April 2005 11:09, Magnus Damm wrote:
> On 4/26/05, Chris Mason <mason@suse.com> wrote:
> > This agrees with my tests here, the time to apply patches is somewhat
> > disk bound, even for the small 100 or 200 patch series.  The io should be
> > coming from data=ordered, since the commits are still every 5 seconds or
> > so.
>
> Yes, as long as you apply the patches to disk that is. I've hacked up
> a small backend tool that applies patches to files kept in memory and
> uses a modifed rabin-karp search to match hunks. So you basically read
> once and write once per file instead of moving data around for each
> applied patch. But it needs two passes.
>
> And no, the source code for the entire Linux kernel is not kept in
> memory - you need a smart frontend to manage the file cache. Drop me a
> line if you are interested.

Sorry, you've lost me.  Right now the cycle goes like this:

1) patch reads patch file, reads source file, writes source file
2) update-cache reads source file, writes git file

Which of those writes are you avoiding?  We have a smart way to manage the 
cache already for the source files...the vm does pretty well.  There's 
nothing to manage for the git files.  For the apply a bunch of patches 
workload, they are write once, read never (except for the index).

-chris


^ permalink raw reply

* Re: [ANNOUNCE] Cogito-0.8 (former git-pasky, big changes!)
From: Martin Atukunda @ 2005-04-26 15:15 UTC (permalink / raw)
  To: git
In-Reply-To: <426DBF94.3010502@timesys.com>

On Tuesday 26 April 2005 07:12, Mike Taht wrote:
> >   Yes, this is a huge change. No, I don't expect any further changes of
> > similar scale. I think the new interface is significantly simpler _and_
> > cleaner than the old one.
>
> Heh. Another huge change would be moving the top level directories
> around a bit.
>
>
> bindings  COPYING  git.spec  Makefile  programs  README.reference  tests
> contrib   doc      include   po        README    src  VERSION
>
> Leaving fixing the makefiles aside as an exercise for the interested
> reader... that's:
<snip>
something like:

--- cogito-0.8.orig/Makefile	2005-04-26 06:02:01.000000000 +0300
+++ cogito-0.8/Makefile	2005-04-26 18:10:52.558786968 +0300
@@ -15,7 +15,7 @@
 # BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely 
randomly
 # break unless your underlying filesystem supports those sub-second times
 # (my ext3 doesn't).
-CFLAGS=-g -O2 -Wall
+CFLAGS=-g -O2 -Wall -Isrc
 
 # Should be changed to /usr/local
 prefix=$(HOME)
@@ -25,19 +25,23 @@
 CC=gcc
 AR=ar
 
-SCRIPTS=git-merge-one-file-script git-prune-script git-pull-script 
git-tag-script
+SCRIPTS=programs/cogito/git-merge-one-file-script 
programs/cogito/git-prune-script \
+	programs/cogito/git-pull-script programs/cogito/git-tag-script
 
-PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
-	cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
-	check-files ls-tree merge-base merge-cache unpack-file git-export \
-	diff-cache convert-cache http-pull rpush rpull rev-list git-mktag \
-	diff-tree-helper
-
-SCRIPT=	commit-id tree-id parent-id cg-Xdiffdo cg-Xmergefile \
-	cg-add cg-admin-lsobj cg-cancel cg-clone cg-commit cg-diff \
-	cg-export cg-help cg-init cg-log cg-ls cg-merge cg-mkpatch \
-	cg-patch cg-pull cg-branch-add cg-branch-ls cg-rm cg-seek cg-status \
-	cg-tag cg-update cg-Xlib
+PROG=   src/update-cache src/show-diff src/init-db src/write-tree 
src/read-tree src/commit-tree \
+	src/cat-file src/fsck-cache src/checkout-cache src/diff-tree src/rev-tree 
src/show-files \
+	src/check-files src/ls-tree src/merge-base src/merge-cache src/unpack-file 
src/git-export \
+	src/diff-cache src/convert-cache src/http-pull src/rpush src/rpull 
src/rev-list src/git-mktag \
+	src/diff-tree-helper
+
+SCRIPT=	programs/cogito/commit-id programs/cogito/tree-id 
programs/cogito/parent-id programs/cogito/cg-Xdiffdo\
+	programs/cogito/cg-Xmergefile programs/cogito/cg-add 
programs/cogito/cg-admin-lsobj \
+	programs/cogito/cg-cancel programs/cogito/cg-clone programs/cogito/cg-commit 
programs/cogito/cg-diff \
+	programs/cogito/cg-export programs/cogito/cg-help programs/cogito/cg-init 
programs/cogito/cg-log \
+	programs/cogito/cg-ls programs/cogito/cg-merge programs/cogito/cg-mkpatch 
programs/cogito/cg-patch \
+	programs/cogito/cg-pull programs/cogito/cg-branch-add 
programs/cogito/cg-branch-ls \
+	programs/cogito/cg-rm programs/cogito/cg-seek programs/cogito/cg-status 
programs/cogito/cg-tag \
+	programs/cogito/cg-update programs/cogito/cg-Xlib
 
 COMMON=	read-cache.o
 
@@ -45,17 +49,17 @@
 
 VERSION= VERSION
 
-LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o
-LIB_FILE=libgit.a
-LIB_H=cache.h object.h
+LIB_OBJS=src/read-cache.o src/sha1_file.o src/usage.o src/object.o 
src/commit.o src/tree.o src/blob.o src/rsh.o
+LIB_FILE=src/libgit.a
+LIB_H=src/cache.h src/object.h src/rsh.h
 
-LIB_H += strbuf.h
-LIB_OBJS += strbuf.o
+LIB_H += src/strbuf.h
+LIB_OBJS += src/strbuf.o
 
-LIB_H += diff.h
-LIB_OBJS += diff.o
+LIB_H += src/diff.h
+LIB_OBJS += src/diff.o
 
-LIBS = -lz
+LIBS = -lz -lcurl
 
 ifdef MOZILLA_SHA1
 	SHA1_HEADER="mozilla-sha1/sha1.h"
@@ -98,8 +102,14 @@
 	install -m755 -d $(DESTDIR)$(bindir)
 	install $(PROG) $(SCRIPTS) $(SCRIPT) $(GEN_SCRIPT) $(DESTDIR)$(bindir)
 
+uninstall:
+	$(foreach file,$(SCRIPT),$(shell rm $(DESTDIR)$(bindir)/$(shell basename 
$(file))))
+	$(foreach file,$(PROG),$(shell rm $(DESTDIR)$(bindir)/$(shell basename 
$(file))))
+	$(foreach file,$(SCRIPTS),$(shell rm $(DESTDIR)$(bindir)/$(shell basename 
$(file))))
+	$(foreach file,$(GEN_SCRIPT),$(shell rm $(DESTDIR)$(bindir)/$(shell basename 
$(file))))
+
 clean:
-	rm -f *.o mozilla-sha1/*.o ppc/*.o $(PROG) $(GEN_SCRIPT) $(LIB_FILE)
+	rm -f *.o src/*.o cogito/*.o mozilla-sha1/*.o ppc/*.o $(PROG) $(GEN_SCRIPT) 
$(LIB_FILE)
 
 backup: clean
 	cd .. ; tar czvf dircache.tar.gz dir-cache

^ permalink raw reply

* Re: Mercurial 0.3 vs git benchmarks
From: Magnus Damm @ 2005-04-26 15:09 UTC (permalink / raw)
  To: Chris Mason; +Cc: Linus Torvalds, Mike Taht, Matt Mackall, linux-kernel, git
In-Reply-To: <200504260713.26020.mason@suse.com>

On 4/26/05, Chris Mason <mason@suse.com> wrote:
> This agrees with my tests here, the time to apply patches is somewhat disk
> bound, even for the small 100 or 200 patch series.  The io should be coming
> from data=ordered, since the commits are still every 5 seconds or so.

Yes, as long as you apply the patches to disk that is. I've hacked up
a small backend tool that applies patches to files kept in memory and
uses a modifed rabin-karp search to match hunks. So you basically read
once and write once per file instead of moving data around for each
applied patch. But it needs two passes.

And no, the source code for the entire Linux kernel is not kept in
memory - you need a smart frontend to manage the file cache. Drop me a
line if you are interested.

/ magnus

^ permalink raw reply

* Re: : Networking
From: Linus Torvalds @ 2005-04-26 14:59 UTC (permalink / raw)
  To: Andrew Morton; +Cc: David S. Miller, git
In-Reply-To: <20050426005725.6bfe6135.akpm@osdl.org>



On Tue, 26 Apr 2005, Andrew Morton wrote:
> 
> So I tried to apply my new get-mm-patches-from-git methodology on this and
> came unstuck.

Yes. You cannot just apply patches, since that will inevitably fail if 
there is any overlap. Which there quite often is.

For this to work in general, you really have to merge the different git 
trees, and generate patches from _that_.

> a) Set up the git repo
> 
> 	mkdir git26
> 	git init rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

Yes. In the long run, you really should need to do this just once, since 
if there is one thing git should be good at, it's just keeping tons of 
random collections of objects around.

The only thing you should be a bit careful about is to remember what the 
"heads" at different points were. In particular, you want to remember 
where you merged with me last was. I've started tagging my releases with 
the git tag facility (_not_ the pasky one, but I think pasky will start 
picking up on that soon enough), so finding a specific release will be 
easy, but if you ever do a non-release merge you'll just have to tag it 
yourself.

> b) Add davem's repo:
> 
> 	git addremote git-net rsync://rsync.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
> 
> c) To generate -mm's linus.patch (patch against 2.6.12-rc3):
> 
> 	git pull origin
> 	git diff -r v2.6.12-rc3 > ../25/patches/linus.patch

You should now also remember the HEAD at this point. That's your "base" 
for any future patches, since you expect other patches to apply on top of 
that.

I think cogito remembers it in the "origin" thing, but you should check.

Save it away in (for example) .git/last-diff-head:

	cat .git/HEAD > .git/last-diff-head

> d) To generate davem's tree (patch against linus's current tree (ie: patch
>    against 2.6.12-rc3+linus.patch)):
> 
> 	git pull git-net

Yes. This should have merged the two (assuming "git pull" does what I 
think it does).

> 	MERGE_BASE=$(merge-base $(cat .git/heads/origin ) $(cat .git/heads/git-net))
> 	git diff -r $MERGE_BASE:$(cat .git/heads/git-net) > ../25/patches/git-net.patch

No. Now you ended up looking at the last common ancestor of the thing you 
merged, and you _should_ have looked at what the difference was _before_ 
the merge. 

So assuming it does remember it in "origin", you should just have done

	git diff -r $(cat .git/last-diff-head):$(cat .git/HEAD)

which basically says "diff between the tree at the time of my last diff,
and the result of the merge".

Then you just update your last-diff-head to reflect that:

	cat .git/HEAD > .git/last-diff-head

and you go on:

> e) Repeat d) for all known git trees.

Yup.

				Linus

^ permalink raw reply

* [PATCH] GIT: Create tar archives of tree on the fly
From: Rene Scharfe @ 2005-04-26 14:42 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

This patch introduces tar-tree, a tool to generate tar archives out of
git repositories.  Basically I took ls-tree and cat-file and melted them
together.  That means tar-tree doesn't create any temporary files, it
just streams out the archive as it goes.

This could be useful for the web interface(s) to provide a downloadable
tarball for any commit or tree object.  For bigger repositories like the
Linux kernel caching the resulting files might be a good idea,
though. :-P

On my machine it's also a bit faster than directly tarring up the
checked out files.  I only ran a few basic checks to make sure the
performance is in the same ballpark, YMMV.

Example usage:

  $ tar-tree a2755a80f40e5794ddc20e00f781af9d6320fafb linux-2.6.12-rc3 |
        bzip2 -9 > linux-2.6.12-rc3.tar.bz2

tar-tree accepts tree IDs and commit IDs.  In the former case all files
within the archive get the current time set as mtime.  Given a commit ID
tar-tree tries to figure out the commit date and sets mtime of all files
to that instead.

Currently the size of a file within the created archive is limited to
2^33-1.  This could be fixed easily within the archive format (with a
Pax extended header), but size is unsigned long throughout GIT, so this
would need to be fixed first.  OTOH I think putting 4GB+ files into a
GIT archive is insane anyway. :]

Path names are limited to 500 characters at the moment.  This can be
stretched if the need should arise.

Patch is against d1df5743809614241883ecad51876607cf432034.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>

diff -Nur a/Makefile b/Makefile
--- a/Makefile	2005-04-26 03:26:45.000000000 +0200
+++ b/Makefile	2005-04-26 08:09:03.000000000 +0200
@@ -18,7 +18,7 @@
 	cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
 	check-files ls-tree merge-base merge-cache unpack-file git-export \
 	diff-cache convert-cache http-pull rpush rpull rev-list git-mktag \
-	diff-tree-helper
+	diff-tree-helper tar-tree
 
 all: $(PROG)
 
diff -Nur a/tar-tree.c b/tar-tree.c
--- a/tar-tree.c	1970-01-01 01:00:00.000000000 +0100
+++ b/tar-tree.c	2005-04-26 08:23:05.000000000 +0200
@@ -0,0 +1,328 @@
+#include <time.h>
+#include "cache.h"
+
+static const char *tar_tree_usage = "tar-tree <key> [basedir]";
+static const char *basedir;
+static time_t archive_time;
+
+struct path_prefix {
+	struct path_prefix *prev;
+	const char *name;
+};
+
+static unsigned long write_out(void *buf, unsigned long size)
+{
+	while (size > 0) {
+		long ret = write(1, buf, size);
+		if (ret < 0) {
+			if (errno == EAGAIN)
+				continue;
+			/* Ignore epipe */
+			if (errno == EPIPE)
+				break;
+			die("tar-tree: %s", strerror(errno));
+		} else if (!ret) {
+			die("tar-tree: disk full?");
+		}
+		size -= ret;
+		buf += ret;
+	}
+	return size;
+}
+
+static unsigned long write_block(void *buf, unsigned long size)
+{
+	unsigned long ret = write_out(buf, size);
+	if (!ret) {
+		unsigned long slack = 512 - size % 512;
+		if (slack % 512) {
+			char padding[511];
+			memset(padding, 0, slack);
+			ret = write_out(padding, slack);
+		}
+	}
+	return ret;
+}
+
+static void append_string(char **p, const char *s)
+{
+	unsigned int len = strlen(s);
+	memcpy(*p, s, len);
+	*p += len;
+}
+
+static void append_char(char **p, char c)
+{
+	**p = c;
+	*p += 1;
+}
+
+static void append_long(char **p, long n)
+{
+	int len = sprintf(*p, "%ld", n);
+	*p += len;
+}
+
+static void append_path_prefix(char **buffer, struct path_prefix *prefix)
+{
+	if (!prefix)
+		return;
+	append_path_prefix(buffer, prefix->prev);
+	append_string(buffer, prefix->name);
+	append_char(buffer, '/');
+}
+
+static unsigned int path_prefix_len(struct path_prefix *prefix)
+{
+	if (!prefix)
+		return 0;
+	return path_prefix_len(prefix->prev) + strlen(prefix->name) + 1;
+}
+
+static void append_path(char **p, int is_dir, const char *basepath,
+			struct path_prefix *prefix, const char *path)
+{
+	if (basepath) {
+		append_string(p, basepath);
+		append_char(p, '/');
+	}
+	append_path_prefix(p, prefix);
+	append_string(p, path);
+	if (is_dir)
+		append_char(p, '/');
+}
+
+static unsigned int path_len(int is_dir, const char *basepath,
+			     struct path_prefix *prefix, const char *path)
+{
+	unsigned int len = 0;
+	if (basepath)
+		len += strlen(basepath) + 1;
+	len += path_prefix_len(prefix) + strlen(path);
+	if (is_dir)
+		len++;
+	return len;
+}
+
+static void append_extended_header_prefix(char **p, const char *keyword,
+					  int valuelen)
+{
+	int reclen = 1 + 1 + strlen(keyword) + 1 + valuelen + 1;
+	if (reclen > 9)
+		reclen++;
+	if (reclen > 99)
+		reclen++;
+	if (reclen > 512)
+		die("tar-tree: extended header too big, wtf?");
+	append_long(p, reclen);
+	append_char(p, ' ');
+	append_string(p, keyword);
+	append_char(p, '=');
+}
+
+static long write_header(const char *, const char *, struct path_prefix *,
+			 const char *, unsigned int, unsigned long);
+
+static long write_extended_header(const char *headerfilename, int is_dir,
+				  const char *basepath,
+				  struct path_prefix *prefix,
+				  const char *path, unsigned int namelen)
+{
+	char records[512], *p;
+	unsigned long ret;
+
+	memset(records, 0, sizeof(records));
+	p = records;
+	append_extended_header_prefix(&p, "path", namelen);
+	append_path(&p, is_dir, basepath, prefix, path);
+	append_char(&p, '\n');
+	ret = write_header(NULL, NULL, NULL, headerfilename, 0100600,
+	                   p - records);
+	if (!ret)
+		ret = write_out(records, sizeof(records));
+	return ret;
+}
+
+static long write_header(const char *sha1, const char *basepath,
+			 struct path_prefix *prefix, const char *path,
+			 unsigned int mode, unsigned long size)
+{
+	unsigned int namelen; 
+	char *p, header[512];
+	unsigned int checksum = 0;
+	int i;
+
+	memset(header, 0, sizeof(header));
+
+	namelen = path_len(S_ISDIR(mode), basepath, prefix, path);
+	if (namelen > 500) {
+		fprintf(stderr, "tar-tree: name too log of object %s\n",
+		        sha1_to_hex(sha1));
+		return size;
+	} else if (namelen > 100) {
+		unsigned long ret;
+		char *sha1_hex = sha1_to_hex(sha1);
+		char headerfilename[51];
+
+		sprintf(header, "%s.data", sha1_hex);
+		sprintf(headerfilename, "%s.paxheader", sha1_hex);
+		ret = write_extended_header(headerfilename, S_ISDIR(mode),
+		                            basepath, prefix, path, namelen);
+		if (ret)
+			return ret;
+	} else {
+		p = header;
+		append_path(&p, S_ISDIR(mode), basepath, prefix, path);
+	}
+
+	if (S_ISDIR(mode))
+		mode |= 0755;	/* GIT doesn't store permissions of dirs */
+	sprintf(&header[100], "%07o", mode & 07777);
+
+	/* XXX: should we provide more meaningful info here? */
+	sprintf(&header[108], "%07o", 0);	/* uid */
+	sprintf(&header[116], "%07o", 0);	/* gid */
+	strncpy(&header[265], "git", 31);	/* uname */
+	strncpy(&header[297], "git", 31);	/* gname */
+
+	sprintf(&header[124], "%011lo", S_ISDIR(mode) ? 0 : size);
+	sprintf(&header[136], "%011lo", archive_time);
+
+	/* typeflag */
+	if (!sha1)
+		header[156] = 'x';	/* extended header */
+	else
+		header[156] = S_ISDIR(mode) ? '5' : '0';
+
+	strcpy(&header[257], "ustar");
+	strcpy(&header[263], "00");
+
+	printf(&header[329], "%07o", 0);	/* devmajor */
+	printf(&header[337], "%07o", 0);	/* devminor */
+
+	memset(&header[148], ' ', 8);
+	for (i = 0; i < sizeof(header); i++)
+		checksum += header[i];
+	sprintf(&header[148], "%07o", checksum & 0x1fffff);
+
+	return write_out(header, sizeof(header));
+}
+
+static unsigned long write_trailer(void)
+{
+	char block[1024];
+	memset(block, 0, sizeof(block));
+	return write_out(block, sizeof(block));
+}
+
+static void traverse_tree(void *buffer, unsigned long size,
+			  struct path_prefix *prefix)
+{
+	struct path_prefix this_prefix;
+	this_prefix.prev = prefix;
+
+	while (size) {
+		int namelen = strlen(buffer)+1;
+		void *eltbuf;
+		char elttype[20];
+		unsigned long eltsize;
+		unsigned char *sha1 = buffer + namelen;
+		char *path = strchr(buffer, ' ') + 1;
+		unsigned int mode;
+
+		if (size < namelen + 20 || sscanf(buffer, "%o", &mode) != 1)
+			die("corrupt 'tree' file");
+		buffer = sha1 + 20;
+		size -= namelen + 20;
+
+		eltbuf = read_sha1_file(sha1, elttype, &eltsize);
+		if (!eltbuf) {
+			error("cannot read %s", sha1_to_hex(sha1));
+			continue;
+		}
+		if (write_header(sha1, basedir, prefix, path, mode, eltsize))
+			exit(0);
+		if (!strcmp(elttype, "tree")) {
+			this_prefix.name = path;
+			traverse_tree(eltbuf, eltsize, &this_prefix);
+		} else if (!strcmp(elttype, "blob")) {
+			if (write_block(eltbuf, eltsize))
+				exit(0);
+		}
+		free(eltbuf);
+	}
+}
+
+time_t commit_time(const unsigned char *sha1)
+{
+	char type[20];
+	void *buffer;
+	unsigned long size;
+	time_t result = 0;
+
+	buffer = read_sha1_file(sha1, type, &size);
+	if (buffer) {
+		char *p = buffer;
+		while (size > 0) {
+			char *endp = memchr(p, '\n', size);
+			if (!endp)
+				break;
+			*endp = '\0';
+			if (endp - p > 10 && !memcmp(p, "committer ", 10)) {
+				char *nump = strrchr(p, ' ');
+				if (!nump)
+					break;
+				*nump = '\0';
+				nump = strrchr(p, ' ');
+				if (!nump)
+					break;
+				result = strtoul(nump, &endp, 10);
+				if (*endp != '\0')
+					result = 0;
+				break;
+			}
+			size -= endp - p - 1;
+			p = endp + 1;
+		}
+	}
+	free(buffer);
+	return result;
+}
+
+int main(int argc, char **argv)
+{
+	unsigned char sha1[20];
+	void *buffer;
+	unsigned long size;
+	unsigned char tree_sha1[20];
+
+	switch (argc) {
+	case 3:
+		basedir = argv[2];
+		/* FALLTHROUGH */
+	case 2:
+		if (get_sha1_hex(argv[1], sha1) < 0)
+			usage(tar_tree_usage);
+		break;
+	default:
+		usage(tar_tree_usage);
+	}
+
+	sha1_file_directory = getenv(DB_ENVIRONMENT);
+	if (!sha1_file_directory)
+		sha1_file_directory = DEFAULT_DB_ENVIRONMENT;
+
+	buffer = read_tree_with_tree_or_commit_sha1(sha1, &size, tree_sha1);
+	if (!buffer)
+		die("unable to read sha1 file");
+	if (memcmp(sha1, tree_sha1, 20))	/* is sha1 a commit object? */
+		archive_time = commit_time(sha1);
+	if (!archive_time)
+		archive_time = time(NULL);
+	if (basedir)
+		write_header("0", NULL, NULL, basedir, 040755, 0);
+	traverse_tree(buffer, size, NULL);
+	free(buffer);
+	write_trailer();
+	return 0;
+}

^ permalink raw reply

* Re: [PATCH] Add archive-tree, a cpio archive creator
From: Rene Scharfe @ 2005-04-26 14:42 UTC (permalink / raw)
  To: Paul Dickson; +Cc: pasky, git
In-Reply-To: <20050425153011.34c93b38.paul@permanentmail.com>

Paul Dickson schrieb:
> Use the "newc" format.  The "odc" will generate a lot of errors on a
>  large filesystem (which I discovered this past weekend).

How is that?  I can only imagine problems with the size of individual
files inside an archive because the size field in the header is limited
to 33 bits.

In any case, I switched to the tar format.  It's more complicated but it
turned out that creating these things is still easy.  Parsing them might
be more of a challenge, but we already have tar for that. :-)

See my other mail for more on the tar creator.  I also rebased it to
core GIT because it's no helper script.

Rene

^ permalink raw reply

* [PATCH GIT 0.6.3] Add an uninstall target to Makefile
From: Martin Atukunda @ 2005-04-26 13:48 UTC (permalink / raw)
  To: git

Add an uninstall target to Makefile that removes installed scripts and
programs.

Signed-off-by: Martin Atukunda <matlads@ds.co.ug>

Index: Makefile
===================================================================
--- 0a9ee5a4d947b998a7ce489242800b39f98eeee5/Makefile  (mode:100644 
sha1:2d7e4cf0464c45b7c5b169bff7e5c4e7768c13a1)
+++ uncommitted/Makefile  (mode:100644)
@@ -82,6 +82,9 @@
        install -m755 -d $(DESTDIR)$(bindir)
        install $(PROG) $(SCRIPT) $(GEN_SCRIPT) $(DESTDIR)$(bindir)
 
+uninstall:
+       cd $(DESTDIR)$(bindir) && rm $(PROG) $(SCRIPT) $(GEN_SCRIPT)
+
 clean:
        rm -f *.o mozilla-sha1/*.o $(PROG) $(GEN_SCRIPT) $(LIB_FILE)

^ permalink raw reply

* Re: [ANNOUNCE] Cogito-0.8 (former git-pasky, big changes!)
From: Morten Welinder @ 2005-04-26 13:36 UTC (permalink / raw)
  To: pasky, git
In-Reply-To: <20050426032422.GQ13467@pasky.ji.cz>

> [...] build and install it, [...]

It assumes the presense of .git/HEAD but doesn't actually fail when missing.

...
gcc -g -O2 -Wall '-DSHA1_HEADER=<openssl/sha.h>' -o diff-tree-helper
diff-tree-helper.c libgit.a -lz -lssl
cat: .git/HEAD: No such file or directory
Invalid id: 
Generating cg-version...

Morten

^ permalink raw reply

* Re: [PATCH] cogito recursive cg-add and cg-rm
From: Joshua T. Corbin @ 2005-04-26 13:21 UTC (permalink / raw)
  To: git
In-Reply-To: <20050426123901.GF18971@pasky.ji.cz>

On 26 April 2005 08:39, Petr Baudis wrote:
> Dear diary, on Tue, Apr 26, 2005 at 06:27:02AM CEST, I got a letter
> where "Joshua T. Corbin" <jcorbin@wunjo.org> told me that...
>
> > This patch adds recursive addition and removal to cg-add and cg-rm,
> > recursion can be disabled with the -n switch.
> >
> > Signed-off-by: Joshua T. Corbin <jcorbin@wunjo.org>
>
> I'd actually prefer -r to explicitly turn the recursion on. That is more
> consistent with the rest of the UNIX world and I really don't feel
> comfortable with cg-rm recursing by default. ;-)
Hmm, I guess for it to work the way I was inteding would take a little more 
work; it should bail if any of the files are not in the repository or are 
locally modified.

> Also please use tabs for indentation.
Will do

-- 
Regards,
Joshua T. Corbin <jcorbin@wunjo.org>

^ permalink raw reply

* Re: [darcs-devel] Re: A darcs that can pull from git
From: David Roundy @ 2005-04-26 12:47 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Juliusz Chroboczek, darcs-devel, Git Mailing List
In-Reply-To: <20050426123445.GE18971@pasky.ji.cz>

On Tue, Apr 26, 2005 at 02:34:45PM +0200, Petr Baudis wrote:
> Dear diary, on Tue, Apr 26, 2005 at 01:06:17PM CEST, I got a letter
> where David Roundy <droundy@abridgegame.org> told me that...
> > Do the git have any suggestions about how to avoid excess downloads or
> > excess copies of a git repository? It seems to me like it would make sense
> > to always download sha1s to ~/.gitcache/, and then hardlink them to the
> > current git repository, so you wouldn't end up ever downloading the same
> > sha1 twice.  Or we should use $GITCACHE/, to give the user some
> > flexibility.  But perhaps this is an already-solved problem, and I've just
> > not noticed...
> 
> I'm not sure about the problem you are actually trying to solve, and I
> didn't manage to guess it quickly just from the mails themselves;
> cg-init /local/path now hardlinks the sha1 objects to the local
> .git/objects directory, so you get no space waste. If you are talking
> about downloading stuff from remote repositories, http-pull might help.

Yeah, what I was wondering about was the scenario where a user does (and
pardon any errors, I haven't actually used cogito) something like

cd foo
cg-init http://remote_repository
cd ../bar
cg-init ../foo

(so far we've only got hard links and everything is great)

http-pull http://remote_repository (downloads a few more commits to bar)
cd ../foo
http-pull http://remote_repository

Does this last pull download the same commits as the previous one? Ideally
it wouldn't.  The whole point of the sha1-named files is that you don't
have to worry about where you got it from.  Ideally the second pull would
get the actual files from ../bar, where they've already been downloaded.

Or perhaps (and this was what I was *really* hoping) all the cogito remote
operations would store a hardlink of their results in a common cache
directory, so that one could actually do

cd foo
cg-init http://remote_repository
cd ../bar
cg-init http://remote_repository

without either downloading anything twice, or wasting any disk space.  In
practice what's more likely in practice is that you'll want to

cd foo
cg-init http://linus_remote_repository
cd ../bar
cg-init http://gregkh_remote_repository

and would like to avoid downloading redundant info.
-- 
David Roundy
http://www.darcs.net

^ permalink raw reply

* Re: [PATCH] cogito recursive cg-add and cg-rm
From: Petr Baudis @ 2005-04-26 12:39 UTC (permalink / raw)
  To: Joshua T. Corbin; +Cc: git
In-Reply-To: <200504260027.03451.jcorbin@wunjo.org>

Dear diary, on Tue, Apr 26, 2005 at 06:27:02AM CEST, I got a letter
where "Joshua T. Corbin" <jcorbin@wunjo.org> told me that...
> This patch adds recursive addition and removal to cg-add and cg-rm, recursion 
> can be disabled with the -n switch.
> 
> Signed-off-by: Joshua T. Corbin <jcorbin@wunjo.org>

I'd actually prefer -r to explicitly turn the recursion on. That is more
consistent with the rest of the UNIX world and I really don't feel
comfortable with cg-rm recursing by default. ;-)

Also please use tabs for indentation.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: Re: A darcs that can pull from git
From: Petr Baudis @ 2005-04-26 12:34 UTC (permalink / raw)
  To: Juliusz Chroboczek, darcs-devel, Git Mailing List
In-Reply-To: <20050426110613.GB20723@abridgegame.org>

Dear diary, on Tue, Apr 26, 2005 at 01:06:17PM CEST, I got a letter
where David Roundy <droundy@abridgegame.org> told me that...
> On Mon, Apr 25, 2005 at 05:12:59PM +0200, Juliusz Chroboczek wrote:
> > > Do you have any plans/ideas for allowing pulls directly from a
> > > remote git repository?
> > 
> > I haven't thought about it yet.  Does anyone have any ideas about how
> > to efficiently pull from git without a complete local copy?
> 
> I don't think so.  My best thought so far would be to have something like a
> ~/.gitcache/, which would store the sha1 objects themselves, so at least
> we'd only end up with *one* local copy.  I'm actually curious what the true
> git people do about this--it would be nice to share a cache.  For darcs'
> purposes, we could prune the cache from time to time.  If we're running
> with a darcs backend, we really only need the recent versions of files and
> trees.
> 
> Do the git have any suggestions about how to avoid excess downloads or
> excess copies of a git repository? It seems to me like it would make sense
> to always download sha1s to ~/.gitcache/, and then hardlink them to the
> current git repository, so you wouldn't end up ever downloading the same
> sha1 twice.  Or we should use $GITCACHE/, to give the user some
> flexibility.  But perhaps this is an already-solved problem, and I've just
> not noticed...

I'm not sure about the problem you are actually trying to solve, and I
didn't manage to guess it quickly just from the mails themselves;
cg-init /local/path now hardlinks the sha1 objects to the local
.git/objects directory, so you get no space waste. If you are talking
about downloading stuff from remote repositories, http-pull might help.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: [ANNOUNCE] Cogito-0.8 (former git-pasky, big changes!)
From: Petr Baudis @ 2005-04-26 12:23 UTC (permalink / raw)
  To: Mike Taht; +Cc: git
In-Reply-To: <426DBF94.3010502@timesys.com>

Dear diary, on Tue, Apr 26, 2005 at 06:12:04AM CEST, I got a letter
where Mike Taht <mike.taht@timesys.com> told me that...
> 
> >  Yes, this is a huge change. No, I don't expect any further changes of
> >similar scale. I think the new interface is significantly simpler _and_
> >cleaner than the old one.
> 
> Heh. Another huge change would be moving the top level directories 
> around a bit.
> 
> 
> bindings  COPYING  git.spec  Makefile  programs  README.reference  tests
> contrib   doc      include   po        README    src  VERSION
> 
> Leaving fixing the makefiles aside as an exercise for the interested 
> reader... that's:

Actually, I've been thinking about this, but I think we just don't need
it *yet*.

And by the time we will need to make things more hierarchical, we will
hopefully have some way to deal with renames sensibly. We need something
for that too - either something ultra-smart as Linus describes, or
explicit renames, but merging not working across renames makes them
total nightmare.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: Mercurial 0.3 vs git benchmarks
From: Chris Mason @ 2005-04-26 11:13 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Mike Taht, Matt Mackall, linux-kernel, git
In-Reply-To: <Pine.LNX.4.58.0504252032500.18901@ppc970.osdl.org>

On Tuesday 26 April 2005 00:00, Linus Torvalds wrote:
> On Mon, 25 Apr 2005, Linus Torvalds wrote:
> > The easiest test-case is Andrew's 198-patch patch-bomb on linux-kernel a
> > few weeks ago: they all apply cleanly to 2.6.12-rc2 (in order), and you
> > can use my "dotest" script to automate the test..
>
> Oh, well. That was so trivial that I just did it:
[ ... ]

> ie the "initial add" is almost twice as fast (because it spends most of
> the time compressing _all_ the files), but the difference in applying 198
> patches is not noticeable at all (because the costs are all elsewhere).
>
> That's 198 patches in less than a minute even with the highest
> compression. That rocks.

This agrees with my tests here, the time to apply patches is somewhat disk 
bound, even for the small 100 or 200 patch series.  The io should be coming 
from data=ordered, since the commits are still every 5 seconds or so.

-chris

^ permalink raw reply

* Re: Re: A darcs that can pull from git
From: David Roundy @ 2005-04-26 11:06 UTC (permalink / raw)
  To: Juliusz Chroboczek; +Cc: Git Mailing List, darcs-devel
In-Reply-To: <7i4qdusxdw.fsf@lanthane.pps.jussieu.fr>

On Mon, Apr 25, 2005 at 05:12:59PM +0200, Juliusz Chroboczek wrote:
> > Do you have any plans/ideas for allowing pulls directly from a
> > remote git repository?
> 
> I haven't thought about it yet.  Does anyone have any ideas about how
> to efficiently pull from git without a complete local copy?

I don't think so.  My best thought so far would be to have something like a
~/.gitcache/, which would store the sha1 objects themselves, so at least
we'd only end up with *one* local copy.  I'm actually curious what the true
git people do about this--it would be nice to share a cache.  For darcs'
purposes, we could prune the cache from time to time.  If we're running
with a darcs backend, we really only need the recent versions of files and
trees.

Do the git have any suggestions about how to avoid excess downloads or
excess copies of a git repository? It seems to me like it would make sense
to always download sha1s to ~/.gitcache/, and then hardlink them to the
current git repository, so you wouldn't end up ever downloading the same
sha1 twice.  Or we should use $GITCACHE/, to give the user some
flexibility.  But perhaps this is an already-solved problem, and I've just
not noticed...

As far as other details, currently we can just walk the tree to find out
what files are needed, right?
-- 
David Roundy
http://www.darcs.net

^ permalink raw reply

* Re: [PATCH] Cogito: do not clobber pre-existing $(bindir)'s mode
From: Sean Neakums @ 2005-04-26 10:52 UTC (permalink / raw)
  To: git
In-Reply-To: <6uwtqpj0oy.fsf@zork.zork.net>

Here is one that actually works.

That'll teach me to be tricky.  (It won't.)


Index: Makefile
===================================================================
--- f262000f302b749e485f5eb971e6aabefbb85680/Makefile  (mode:100644 sha1:4f01bbbbb3fd0e53e9ce968f167b6dae68fcfa92)
+++ uncommitted/Makefile  (mode:100644)
@@ -95,7 +95,7 @@
 	@chmod +x $@
 
 install: $(PROG) $(SCRIPTS) $(SCRIPT) $(GEN_SCRIPT)
-	install -m755 -d $(DESTDIR)$(bindir)
+	[ -d $(DESTDIR)$(bindir) ] || install -m755 -d $(DESTDIR)$(bindir)
 	install $(PROG) $(SCRIPTS) $(SCRIPT) $(GEN_SCRIPT) $(DESTDIR)$(bindir)
 
 clean:

-- 
Dag vijandelijk luchtschip de huismeester is dood

^ permalink raw reply

* [PATCH] Cogito: do not clobber pre-existing $(bindir)'s mode
From: Sean Neakums @ 2005-04-26 10:23 UTC (permalink / raw)
  To: git


Index: Makefile
===================================================================
--- f262000f302b749e485f5eb971e6aabefbb85680/Makefile  (mode:100644 sha1:4f01bbbbb3fd0e53e9ce968f167b6dae68fcfa92)
+++ uncommitted/Makefile  (mode:100644)
@@ -95,7 +95,7 @@
 	@chmod +x $@
 
 install: $(PROG) $(SCRIPTS) $(SCRIPT) $(GEN_SCRIPT)
-	install -m755 -d $(DESTDIR)$(bindir)
+	[ ! -d $(DESTDIR)$(bindir) ] && install -m755 -d $(DESTDIR)$(bindir)
 	install $(PROG) $(SCRIPTS) $(SCRIPT) $(GEN_SCRIPT) $(DESTDIR)$(bindir)
 
 clean:

-- 
Dag vijandelijk luchtschip de huismeester is dood

^ permalink raw reply

* [PATCH] Convert shortlog to handle cogito (cg-log) output
From: Ryan Anderson @ 2005-04-26  8:39 UTC (permalink / raw)
  To: Matthias Andree; +Cc: Linus Torvalds, git


Convert "shortlog" to understand cogito's cg-log output format instead
of "bk changes" format.

Cogito (and by inference, "git" in general) have a different log output
format than BitKeeper.  This log format seems somewhat simpler to parse.

The following patch is a *bare minimum* conversion to make "shortlog"
provide corrected output the Cogito script "cg-log".

(This is clearly not sufficient, and not intended for application to any
rea tree, as a lot of BitKeeper domain knowledge remains, but this
should be enough for Linus to provide changelogs in the "shortlog"
format again, and hopefully to serve as a template for further
modifications by others.)

Signed-Off-By: Ryan Anderson <ryan@michonline.com>

--- cogito-tools/shortlog	2005-04-26 04:22:01.000000000 -0400
+++ cogito-tools/git-shortlog	2005-04-26 04:36:52.000000000 -0400
@@ -3052,7 +3052,7 @@
       }
 
     if (defined $address and $opt{multi}
-	and m{^[^<[:space:]]} and not m{^ChangeSet@}) {
+	and m{^[^<[:space:]]} and not m{^commit }) {
       # if we are in multi mode, if we encounter a non-address
       # left-justified line, flush all data and print the header. The
       # 'defined $address' trick lets this only trigger to switch back
@@ -3063,13 +3063,14 @@
       @prolog = ($_);
       undef %$log;
       undef $address;
-    } elsif (m{^<([^>]+)>} or m{^ChangeSet@[0-9.]+,\s*[-0-9:+ ]+,\s*(\S+)}) {
+    } elsif (m{^<([^>]+)>} or m{^author (.*) <(.*)>}) {
       # go figure if a line starts with an address, if so, take it
       # resolve the address to a name if possible
       append_item(%$log, @cur); @cur = ();
-      $address = lc($1);
+      $address = lc($2);
       $address =~ s/\[[^]]+\]$//;
       $name = rmap_address($address, 1);
+      $name = $1 if ($name eq $address);
       $author = treat_addr_name($address, $name);
       $first = 1;
       $firstpar = 1;
@@ -3093,25 +3094,28 @@
       } else {
 	  print STDERR " SKIPPED SIGNED-OFF-BY  $author\n" if $debug;
       }
-    } elsif ($first) {
+    } elsif ($first && m/^(?:[[:space:]]{4}|\t)(.*)$/) {
       # we have a "first" line after an address, take it,
       # strip common redundant tags
+      
+      my $comment = $1;
 
       # kill "PATCH" tag
-      s/^\s*\[PATCH\]//;
-      s/^\s*PATCH//;
-      s/^\s*[-:]+\s*//;
+      $comment =~ s/^\s*\[PATCH\]//;
+      $comment =~ s/^\s*PATCH//;
+      $comment =~ s/^\s*[-:]+\s*//;
 
       # strip trailing colon or period, and if we strip one,
       # we don't parse further lines as part of the first paragraph
-      if (s/[:.]+\s*$//) { $firstpar = 0; }
+      if ($comment =~ s/[:.]+\s*$//) { $firstpar = 0; }
 
       # kill leading and trailing whitespace for consistent indentation
-      s/^\s+//; s/\s+$//;
+      $comment =~ s/^\s+//; s/\s+$//;
 
-      push @cur, $_;
+      push @cur, $comment;
       $first = 0;
-    } elsif (defined $address) {
+
+    } elsif (defined $address && m/^(?:[[:space:]]{4}|\t)(.*)$/ ) {
       # second or subsequent lines -- if in first paragraph,
       # append this line to the first log line.
       if (m/^\s*$/) { $firstpar = 0; }
@@ -3124,6 +3128,10 @@
       }
       # we don't parse further lines as part of the first paragraph
       if (s/[:.]+\s*$//) { $firstpar = 0; }
+
+    } elsif (m/^(commit|tree|parent|committer) / || m/^\s*$/) {
+      # Skip unused header lines
+
     } else {
       # store header before a changelog
       push @prolog, $_;


-- 

Ryan Anderson
  sometimes Pug Majere

^ permalink raw reply

* Re: : Networking
From: Andrew Morton @ 2005-04-26  7:57 UTC (permalink / raw)
  To: David S. Miller; +Cc: torvalds, git
In-Reply-To: <20050425214326.512b006e.davem@davemloft.net>

"David S. Miller" <davem@davemloft.net> wrote:
>
> Linus, please pull from:
> 
>  	rsync://rsync.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git

So I tried to apply my new get-mm-patches-from-git methodology on this and
came unstuck.

-mm kernels consist of a series of patches against the most recent release
(2.6.12-rc3 today):

	linus.patch		(Linus' changes since 2.6.12-rc3)
	git-net.patch		(Davem's changes wrt Linus's latest tree)
	etc...

The algorithm is:


a) Set up the git repo

	mkdir git26
	git init rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

	(Futz around in `git log' output to identify the v2.6.12-rc3 commit, do
	 `git tag v2.6.12-rc3 a2755a80f40e5794ddc20e00f781af9d6320fafb')

b) Add davem's repo:

	git addremote git-net rsync://rsync.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git

c) To generate -mm's linus.patch (patch against 2.6.12-rc3):

	git pull origin
	git diff -r v2.6.12-rc3 > ../25/patches/linus.patch

d) To generate davem's tree (patch against linus's current tree (ie: patch
   against 2.6.12-rc3+linus.patch)):

	git pull git-net
	MERGE_BASE=$(merge-base $(cat .git/heads/origin ) $(cat .git/heads/git-net))
	git diff -r $MERGE_BASE:$(cat .git/heads/git-net) > ../25/patches/git-net.patch

e) Repeat d) for all known git trees.



But git-net.patch has a bunch of bluetooth stuff in it which is already in
Linus's tree.  And git-net.patch modifies net/sched/simple.c, which doesn't
appear in either 2.6.12-rc3 or in current -linus.


Doing step d) by hand:


	bix:/usr/src/git26> cat .git/heads/origin
	b453257f057b834fdf9f4a6ad6133598b79bd982
	bix:/usr/src/git26> cat .git/heads/git-net
	5523662c4cd585b892811d7bb3e25d9a787e19b3
	bix:/usr/src/git26> merge-base b453257f057b834fdf9f4a6ad6133598b79bd982 5523662c4cd585b892811d7bb3e25d9a787e19b3
	25ee7e3832951cf5896b194f6cd929a44863f419

	bix:/usr/src/git26> cat-file commit 25ee7e3832951cf5896b194f6cd929a44863f419
	tree 5b6486ded5188e41ac9bc81ad4a5e2bd746f7ede
	parent 056de2fa12febe02597f971eb6ea8f2cc9c9b06e
	author Adrian Bunk <bunk@stusta.de> 1114442294 -0700
	committer Linus Torvalds <torvalds@ppc970.osdl.org> 1114442294 -0700

	[PATCH] fs/aio.c: make some code static

	This patch makes some needlessly global code static.

	Signed-off-by: Adrian Bunk <bunk@stusta.de>
	Acked-by: Benjamin LaHaise <bcrl@kvack.org>
	Signed-off-by: Linus Torvalds <torvalds@osdl.org>


That seems to be a reasonable gca.  It's the last thing which Linus added
prior to merging the ARM patches, which presumably weren't in Dave's tree.

So let's try to grab davem's diff wrt that gca:

bix:/usr/src/git26> git diff -r 25ee7e3832951cf5896b194f6cd929a44863f419:5523662c4cd585b892811d7bb3e25d9a787e19b3 | diffstat
 drivers/net/tg3.c                            |   73 ++++++++++++++-------------
 net/bluetooth/af_bluetooth.c                 |    1 
 net/bluetooth/bnep/sock.c                    |    1 
 net/bluetooth/cmtp/capi.c                    |    1 
 net/bluetooth/cmtp/core.c                    |    1 
 net/bluetooth/cmtp/sock.c                    |    1 
 net/bluetooth/hci_conn.c                     |    1 
 net/bluetooth/hci_core.c                     |    1 
 net/bluetooth/hci_event.c                    |    1 
 net/bluetooth/hci_sock.c                     |    1 
 net/bluetooth/hidp/core.c                    |    1 
 net/bluetooth/hidp/sock.c                    |    1 
 net/bluetooth/l2cap.c                        |    1 
 net/bluetooth/rfcomm/sock.c                  |    1 
 net/bluetooth/sco.c                          |    1 
 net/core/rtnetlink.c                         |    1 
 net/core/scm.c                               |    1 
 net/core/sock.c                              |    1 
 net/ipv4/af_inet.c                           |    1 
 net/ipv4/ip_output.c                         |    2 
 net/ipv4/netfilter/ip_conntrack_ftp.c        |    4 -
 net/ipv4/netfilter/ip_conntrack_standalone.c |    7 --
 net/ipv4/tcp_input.c                         |    1 
 net/ipv6/af_inet6.c                          |    1 
 net/netlink/af_netlink.c                     |    1 
 net/sched/simple.c                           |   18 ------
 net/unix/af_unix.c                           |    1 
 27 files changed, 46 insertions(+), 80 deletions(-)

And that's the bad patch.

What did I do wrong?

Can someone suggest a better approach?

Thanks.


^ permalink raw reply

* [PATCH] Diff-tree-helper take two.
From: Junio C Hamano @ 2005-04-26  7:57 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <7vll76ouk0.fsf@assigned-by-dhcp.cox.net>

This patch reworks the diff-tree-helper and show-diff to further
make external diff command interface simpler.  These commands
now honor GIT_EXTERNAL_DIFF environment variable which can point
at an arbitrary program that takes 7 parameters:

  name file1 file1-sha1 file1-mode file2 file2-sha1 file2-mode

The parameters for an external diff command are as follows:

  name        this invocation of the command is to emit diff
	      for the named cache/tree entry.

  file1       pathname that holds the contents of the first
	      file.  This can be a file inside the working
	      tree, or a temporary file created from the blob
	      object, or /dev/null.  The command should not
	      attempt to unlink it -- the temporary is
	      unlinked by the caller.

  file1-sha1  sha1 hash if file1 is a blob object, or "."
	      otherwise.

  file1-mode  mode bits for file1, or "." for a deleted file.

If GIT_EXTERNAL_DIFF environment variable is not set, the
default is to invoke diff with the set of parameters old
show-diff used to use.  This built-in implementation honors the
GIT_DIFF_CMD and GIT_DIFF_OPTS environment variables as before.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

diff-tree-helper.c       |  242 +++++++-------------------------------------
diff.c                   |  254 ++++++++++++++++++++++++++++++++++++++---------
diff.h                   |   34 ++++--
jit-external-diff-script |   14 ++
show-diff.c              |   17 ---
5 files changed, 288 insertions(+), 273 deletions(-)

--- k/diff-tree-helper.c
+++ l/diff-tree-helper.c
@@ -1,3 +1,6 @@
+/*
+ * Copyright (C) 2005 Junio C Hamano
+ */
 #include "cache.h"
 #include "strbuf.h"
 #include "diff.h"
@@ -17,15 +20,22 @@ static int matches_pathspec(const char *
 	return 0;
 }
 
-static int parse_oneside_change(const char *cp, unsigned char *sha1,
-				char *path) {
+static int parse_oneside_change(const char *cp, struct diff_spec *one,
+				char *path)
+{
 	int ch;
-	while ((ch = *cp) && '0' <= ch && ch <= '7')
-		cp++; /* skip mode bits */
+
+	one->file_valid = one->sha1_valid = 1;
+	one->mode = 0;
+	while ((ch = *cp) && '0' <= ch && ch <= '7') {
+		one->mode = (one->mode << 3) | (ch - '0');
+		cp++;
+	}
+
 	if (strncmp(cp, "\tblob\t", 6))
 		return -1;
 	cp += 6;
-	if (get_sha1_hex(cp, sha1))
+	if (get_sha1_hex(cp, one->u.sha1))
 		return -1;
 	cp += 40;
 	if (*cp++ != '\t')
@@ -34,31 +44,20 @@ static int parse_oneside_change(const ch
 	return 0;
 }
 
-#define STATUS_CACHED    0 /* cached and sha1 valid */
-#define STATUS_ABSENT    1 /* diff-tree says old removed or new added */
-#define STATUS_UNCACHED  2 /* diff-cache output: read from working tree */
-
 static int parse_diff_tree_output(const char *buf,
-				  unsigned char *old_sha1,
-				  int *old_status,
-				  unsigned char *new_sha1,
-				  int *new_status,
+				  struct diff_spec *old,
+				  struct diff_spec *new,
 				  char *path) {
 	const char *cp = buf;
 	int ch;
-	static unsigned char null_sha[20] = { 0, };
 
 	switch (*cp++) {
 	case '+':
-		*old_status = STATUS_ABSENT;
-		*new_status = (memcmp(new_sha1, null_sha, sizeof(null_sha)) ?
-			       STATUS_CACHED : STATUS_UNCACHED);
-		return parse_oneside_change(cp, new_sha1, path);
+		old->file_valid = 0;
+		return parse_oneside_change(cp, new, path);
 	case '-':
-		*new_status = STATUS_ABSENT;
-		*old_status = (memcmp(old_sha1, null_sha, sizeof(null_sha)) ?
-			       STATUS_CACHED : STATUS_UNCACHED);
-		return parse_oneside_change(cp, old_sha1, path);
+		new->file_valid = 0;
+		return parse_oneside_change(cp, old, path);
 	case '*':
 		break;
 	default:
@@ -66,191 +65,36 @@ static int parse_diff_tree_output(const 
 	}
 	
 	/* This is for '*' entries */
-	while ((ch = *cp) && ('0' <= ch && ch <= '7'))
-		cp++; /* skip mode bits */
+	old->file_valid = old->sha1_valid = 1;
+	new->file_valid = new->sha1_valid = 1;
+
+	old->mode = new->mode = 0;
+	while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
+		old->mode = (old->mode << 3) | (ch - '0');
+		cp++;
+	}
 	if (strncmp(cp, "->", 2))
 		return -1;
 	cp += 2;
-	while ((ch = *cp) && ('0' <= ch && ch <= '7'))
-		cp++; /* skip mode bits */
+	while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
+		new->mode = (new->mode << 3) | (ch - '0');
+		cp++;
+	}
 	if (strncmp(cp, "\tblob\t", 6))
 		return -1;
 	cp += 6;
-	if (get_sha1_hex(cp, old_sha1))
+	if (get_sha1_hex(cp, old->u.sha1))
 		return -1;
 	cp += 40;
 	if (strncmp(cp, "->", 2))
 		return -1;
 	cp += 2;
-	if (get_sha1_hex(cp, new_sha1))
+	if (get_sha1_hex(cp, new->u.sha1))
 		return -1;
 	cp += 40;
 	if (*cp++ != '\t')
 		return -1;
 	strcpy(path, cp);
-	*old_status = (memcmp(old_sha1, null_sha, sizeof(null_sha)) ?
-		       STATUS_CACHED : STATUS_UNCACHED);
-	*new_status = (memcmp(new_sha1, null_sha, sizeof(null_sha)) ?
-		       STATUS_CACHED : STATUS_UNCACHED);
-	return 0;
-}
-
-static int sha1err(const char *path, const unsigned char *sha1)
-{
-	return error("diff-tree-helper: unable to read sha1 file of %s (%s)",
-		     path, sha1_to_hex(sha1));
-}
-
-static int fserr(const char *path)
-{
-	return error("diff-tree-helper: unable to read file %s", path);
-}
-
-static char *map_whole_file(const char *path, unsigned long *size) {
-	int fd;
-	struct stat st;
-	void *buf;
-
-	if ((fd = open(path, O_RDONLY)) < 0) {
-		error("diff-tree-helper: unable to read file %s", path);
-		return 0;
-	}
-	if (fstat(fd, &st) < 0) {
-		close(fd);
-		error("diff-tree-helper: unable to stat file %s", path);
-		return 0;
-	}
-	*size = st.st_size;
-	buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-	close(fd);
-	return buf;
-}
-
-static int show_diff(const unsigned char *old_sha1, int old_status,
-		     const unsigned char *new_sha1, int new_status,
-		     const char *path, int reverse_diff)
-{
-	char other[PATH_MAX];
-	unsigned long size;
-	char type[20];
-	int fd;
-	int reverse;
-	void *blob = 0;
-	const char *fs = 0;
-	int need_unmap = 0;
-	int need_unlink = 0;
-
-
-	switch (old_status) {
-	case STATUS_CACHED:
-		blob = read_sha1_file(old_sha1, type, &size);
-		if (! blob)
-			return sha1err(path, old_sha1);
-			
-		switch (new_status) {
-		case STATUS_CACHED:
-			strcpy(other, ".diff_tree_helper_XXXXXX");
-			fd = mkstemp(other);
-			if (fd < 0)
-				die("unable to create temp-file");
-			if (write(fd, blob, size) != size)
-				die("unable to write temp-file");
-			close(fd);
-			free(blob);
-
-			blob = read_sha1_file(new_sha1, type, &size);
-			if (! blob)
-				return sha1err(path, new_sha1);
-
-			need_unlink = 1;
-			/* new = blob, old = fs */
-			reverse = !reverse_diff;
-			fs = other;
-			break;
-
-		case STATUS_ABSENT:
-		case STATUS_UNCACHED:
-			fs = ((new_status == STATUS_ABSENT) ?
-			      "/dev/null" : path);
-			reverse = reverse_diff;
-			break;
-
-		default:
- 			reverse = reverse_diff;
-		}
-		break;
-
-	case STATUS_ABSENT:
-		switch (new_status) {
-		case STATUS_CACHED:
-			blob = read_sha1_file(new_sha1, type, &size);
-			if (! blob)
-				return sha1err(path, new_sha1);
-			/* old = fs, new = blob */
-			fs = "/dev/null";
-			reverse = !reverse_diff;
-			break;
-
-		case STATUS_ABSENT:
-			return error("diff-tree-helper: absent from both old and new?");
-		case STATUS_UNCACHED:
-			fs = path;
-			blob = strdup("");
-			size = 0;
-			/* old = blob, new = fs */
-			reverse = reverse_diff;
-			break;
-		default:
-			reverse = reverse_diff;
-		}
-		break;
-
-	case STATUS_UNCACHED:
-		fs = path; /* old = fs, new = blob */
-		reverse = !reverse_diff;
-
-		switch (new_status) {
-		case STATUS_CACHED:
-			blob = read_sha1_file(new_sha1, type, &size);
-			if (! blob)
-				return sha1err(path, new_sha1);
-			break;
-
-		case STATUS_ABSENT:
-			blob = strdup("");
-			size = 0;
-			break;
-
-		case STATUS_UNCACHED:
-			/* old = fs */
-			blob = map_whole_file(path, &size);
-			if (! blob)
-				return fserr(path);
-			need_unmap = 1;
-			break;
-		default:
-			reverse = reverse_diff;
-		}
-		break;
-
-	default:
-		reverse = reverse_diff;
-	}
-	
-	if (fs)
-		show_differences(fs,
-				 path, /* label */
-				 blob,
-				 size,
-				 reverse /* 0: diff blob fs
-					    1: diff fs blob */);
-
-	if (need_unlink)
-		unlink(other);
-	if (need_unmap && blob)
-		munmap(blob, size);
-	else
-		free(blob);
 	return 0;
 }
 
@@ -275,28 +119,20 @@ int main(int ac, char **av) {
 	}
 	/* the remaining parameters are paths patterns */
 
-	prepare_diff_cmd();
-
 	while (1) {
-		int old_status, new_status;
-		unsigned char old_sha1[20], new_sha1[20];
+		struct diff_spec old, new;
 		char path[PATH_MAX];
 		read_line(&sb, stdin, line_termination);
 		if (sb.eof)
 			break;
-		if (parse_diff_tree_output(sb.buf,
-					   old_sha1, &old_status,
-					   new_sha1, &new_status,
-					   path)) {
+		if (parse_diff_tree_output(sb.buf, &old, &new, path)) { 
 			fprintf(stderr, "cannot parse %s\n", sb.buf);
 			continue;
 		}
-		if (1 < ac && ! matches_pathspec(path, av+1, ac-1))
+		if (1 < ac && !matches_pathspec(path, av+1, ac-1))
 			continue;
 
-		show_diff(old_sha1, old_status,
-			  new_sha1, new_status,
-			  path, reverse_diff);
+		run_external_diff(path, &old, &new);
 	}
 	return 0;
 }
--- k/diff.c
+++ l/diff.c
@@ -1,13 +1,22 @@
+/*
+ * Copyright (C) 2005 Junio C Hamano
+ */
+#include <sys/types.h>
+#include <sys/wait.h>
 #include "cache.h"
 #include "diff.h"
 
-static char *diff_cmd = "diff -L 'k/%s' -L 'l/%s' ";
-static char *diff_opts = "-p -u";
-static char *diff_arg_forward  = " - '%s'";
-static char *diff_arg_reverse  = " '%s' -";
+static char *diff_cmd = "diff -L'k/%s' -L'l/%s'";
+static char *diff_opts = "-pu";
 
-void prepare_diff_cmd(void)
+static const char *external_diff(void)
 {
+	static char *external_diff_cmd = NULL;
+	static int done_preparing = 0;
+
+	if (done_preparing)
+		return external_diff_cmd;
+
 	/*
 	 * Default values above are meant to match the
 	 * Linux kernel development style.  Examples of
@@ -17,8 +26,15 @@ void prepare_diff_cmd(void)
 	 * GIT_DIFF_CMD="diff -L '%s' -L '%s'"
 	 * GIT_DIFF_OPTS="-c";
 	 */
+	if (getenv("GIT_EXTERNAL_DIFF"))
+		external_diff_cmd = getenv("GIT_EXTERNAL_DIFF");
+
+	/* In case external diff fails... */
 	diff_cmd = getenv("GIT_DIFF_CMD") ? : diff_cmd;
 	diff_opts = getenv("GIT_DIFF_OPTS") ? : diff_opts;
+
+	done_preparing = 1;
+	return external_diff_cmd;
 }
 
 /* Help to copy the thing properly quoted for the shell safety.
@@ -58,49 +74,195 @@ static char *sq_expand(const char *src)
 	return buf;
 }
 
-void show_differences(const char *name, /* filename on the filesystem */
-		      const char *label, /* diff label to use */
-		      void *old_contents, /* contents in core */
-		      unsigned long long old_size, /* size in core */
-		      int reverse /* 0: diff core file
-				     1: diff file core */)
-{
-	FILE *f;
-	char *name_sq = sq_expand(name);
-	const char *label_sq = (name != label) ? sq_expand(label) : name_sq;
-	char *diff_arg = reverse ? diff_arg_reverse : diff_arg_forward;
-	int cmd_size = strlen(name_sq) + strlen(label_sq) * 2 +
-		strlen(diff_cmd) + strlen(diff_opts) + strlen(diff_arg);
+static struct diff_tempfile {
+	const char *name;
+	char hex[41];
+	char mode[10];
+	char tmp_path[50];
+} diff_temp[2];
+
+static void builtin_diff(const char *name,
+			 struct diff_tempfile *temp)
+{
+	static char *diff_arg  = "'%s' '%s'";
+	const char *name_1_sq = sq_expand(temp[0].name);
+	const char *name_2_sq = sq_expand(temp[1].name);
+	const char *name_sq = sq_expand(name);
+
+	/* diff_cmd and diff_arg have 4 %s in total which makes
+	 * the sum of these strings 8 bytes larger than required.
+	 * we use 2 spaces around diff-opts, and we need to count
+	 * terminating NUL, so we subtract 5 here.
+	 */
+	int cmd_size = (strlen(diff_cmd) + 
+			strlen(name_sq) * 2 +
+			strlen(diff_opts) +
+			strlen(diff_arg) +
+			strlen(name_1_sq) + strlen(name_2_sq)
+			- 5);
 	char *cmd = malloc(cmd_size);
-	int next_at;
+	int next_at = 0;
+
+	next_at += snprintf(cmd+next_at, cmd_size-next_at,
+			    diff_cmd, name_sq, name_sq);
+	next_at += snprintf(cmd+next_at, cmd_size-next_at,
+			    " %s ", diff_opts);
+	next_at += snprintf(cmd+next_at, cmd_size-next_at,
+			    diff_arg, name_1_sq, name_2_sq);
+	execlp("/bin/sh","sh", "-c", cmd, NULL);
+}
+
+static void prepare_temp_file(const char *name,
+			      struct diff_tempfile *temp,
+			      struct diff_spec *one)
+{
+	static unsigned char null_sha1[20] = { 0, };
 
-	fflush(stdout);
-	next_at = snprintf(cmd, cmd_size, diff_cmd, label_sq, label_sq);
-	next_at += snprintf(cmd+next_at, cmd_size-next_at, "%s", diff_opts);
-	next_at += snprintf(cmd+next_at, cmd_size-next_at, diff_arg, name_sq);
-	f = popen(cmd, "w");
-	if (old_size)
-		fwrite(old_contents, old_size, 1, f);
-	pclose(f);
-	if (label_sq != name_sq)
-		free((void*)label_sq); /* constness */
-	free(name_sq);
-	free(cmd);
-}
-
-void show_diff_empty(const unsigned char *sha1,
-		     const char *name,
-		     int reverse)
-{
-	char *old;
-	unsigned long int size;
-	unsigned char type[20];
-
-	old = read_sha1_file(sha1, type, &size);
-	if (! old) {
-		error("unable to read blob object for %s (%s)", name,
-		      sha1_to_hex(sha1));
+	if (!one->file_valid) {
+	not_a_valid_file:
+		temp->name = "/dev/null";
+		strcpy(temp->hex, ".");
+		strcpy(temp->mode, ".");
 		return;
 	}
-	show_differences("/dev/null", name, old, size, reverse);
+
+	if (one->sha1_valid &&
+	    !memcmp(one->u.sha1, null_sha1, sizeof(null_sha1))) {
+		one->sha1_valid = 0;
+		one->u.name = name;
+	}
+
+	if (!one->sha1_valid) {
+		struct stat st;
+		temp->name = one->u.name;
+		if (stat(temp->name, &st) < 0) {
+			if (errno == ENOENT)
+				goto not_a_valid_file;
+			die("stat(%s): %s", temp->name, strerror(errno));
+		}
+		strcpy(temp->hex, ".");
+		sprintf(temp->mode, "%06o",
+			S_IFREG |ce_permissions(st.st_mode));
+	}
+	else {
+		int fd;
+		void *blob;
+		char type[20];
+		unsigned long size;
+
+		blob = read_sha1_file(one->u.sha1, type, &size);
+		if (!blob || strcmp(type, "blob"))
+			die("unable to read blob object for %s (%s)",
+			    name, sha1_to_hex(one->u.sha1));
+
+		strcpy(temp->tmp_path, ".diff_XXXXXX");
+		fd = mkstemp(temp->tmp_path);
+		if (fd < 0)
+			die("unable to create temp-file");
+		if (write(fd, blob, size) != size)
+			die("unable to write temp-file");
+		close(fd);
+		free(blob);
+		temp->name = temp->tmp_path;
+		strcpy(temp->hex, sha1_to_hex(one->u.sha1));
+		temp->hex[40] = 0;
+		sprintf(temp->mode, "%06o", one->mode);
+	}
+}
+
+static void remove_tempfile(void)
+{
+	int i;
+
+	for (i = 0; i < 2; i++)
+		if (diff_temp[i].name == diff_temp[i].tmp_path) {
+			unlink(diff_temp[i].name);
+			diff_temp[i].name = NULL;
+		}
+}
+
+/* An external diff command takes:
+ *
+ * diff-cmd name infile1 infile1-sha1 infile1-mode \
+ *               infile2 infile2-sha1 infile2-mode.
+ *
+ */
+void run_external_diff(const char *name,
+		       struct diff_spec *one,
+		       struct diff_spec *two)
+{
+	struct diff_tempfile *temp = diff_temp;
+	int pid, status;
+	static int atexit_asked = 0;
+
+	prepare_temp_file(name, &temp[0], one);
+	prepare_temp_file(name, &temp[1], two);
+	if (! atexit_asked &&
+	    (temp[0].name == temp[0].tmp_path ||
+	     temp[1].name == temp[1].tmp_path)) {
+		atexit_asked = 1;
+		atexit(remove_tempfile);
+	}
+
+	fflush(NULL);
+	pid = fork();
+	if (pid < 0)
+		die("unable to fork");
+	if (!pid) {
+		const char *pgm = external_diff();
+		if (pgm)
+			execlp(pgm, pgm,
+			       name,
+			       temp[0].name, temp[0].hex, temp[0].mode,
+			       temp[1].name, temp[1].hex, temp[1].mode,
+			       NULL);
+		/*
+		 * otherwise we use the built-in one.
+		 */
+		builtin_diff(name, temp);
+		exit(0);
+	}
+	if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status))
+		die("diff program failed");
+
+	remove_tempfile();
+}
+
+void show_diff_empty(const struct cache_entry *ce, int reverse)
+{
+	struct diff_spec spec[2], *one, *two;
+
+	memcpy(spec[0].u.sha1, ce->sha1, 20);
+	spec[0].mode = ntohl(ce->ce_mode);
+	spec[0].sha1_valid = spec[0].file_valid = 1;
+	spec[1].file_valid = 0;
+
+	if (reverse) {
+		one = spec + 1; two = spec;
+	} else {
+		one = spec; two = one + 1;
+	}
+
+	run_external_diff(ce->name, one, two);
+}
+
+void show_differences(const struct cache_entry *ce, int reverse) 
+{
+	struct diff_spec spec[2], *one, *two;
+
+	memcpy(spec[0].u.sha1, ce->sha1, 20);
+	spec[0].mode = ntohl(ce->ce_mode);
+	spec[0].sha1_valid = spec[0].file_valid = 1;
+
+	spec[1].u.name = ce->name; /* the name we stated */
+	spec[1].sha1_valid = 0;
+	spec[1].file_valid = 1;
+
+	if (reverse) {
+		one = spec + 1; two = spec;
+	} else {
+		one = spec; two = one + 1;
+	}
+
+	run_external_diff(ce->name, one, two);
 }
--- k/diff.h
+++ l/diff.h
@@ -1,17 +1,31 @@
+/*
+ * Copyright (C) 2005 Junio C Hamano
+ */
 #ifndef DIFF_H
 #define DIFF_H
 
-extern void prepare_diff_cmd(void);
+/* These two are for backward compatibility with show-diff;
+ * new users should not use them.
+ */
+extern void show_differences(const struct cache_entry *ce, int reverse);
+extern void show_diff_empty(const struct cache_entry *ce, int reverse);
 
-extern void show_differences(const char *name, /* filename on the filesystem */
-			     const char *label, /* diff label to use */
-			     void *old_contents, /* contents in core */
-			     unsigned long long old_size, /* size in core */
-			     int reverse /* 0: diff core file
-					    1: diff file core */);
+struct diff_spec {
+	union {
+		const char *name;       /* path on the filesystem */
+		unsigned char sha1[20]; /* blob object ID */
+	} u;
+	unsigned short mode;	 /* file mode */
+	unsigned sha1_valid : 1; /* if true, use u.sha1 and trust mode.
+				  * (however with a NULL SHA1, read them
+				  * from the file!).
+				  * if false, use u.name and read mode from
+				  * the filesystem.
+				  */
+	unsigned file_valid : 1; /* if false the file does not even exist */
+};
 
-extern void show_diff_empty(const unsigned char *sha1,
-			    const char *name,
-			    int reverse);
+extern void run_external_diff(const char *name,
+			      struct diff_spec *, struct diff_spec *);
 
 #endif /* DIFF_H */
--- k/jit-external-diff-script
+++ l/jit-external-diff-script
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Copyright (C) 2005 Junio C Hamano
+#
+
+name="$1" name1="$2" sha11="$3" mode1="$4"
+          name2="$5" sha12="$6" mode2="$7"
+
+case "$sha11" in .) sha11=file-not-in-blob-but-in-the-working-tree ;; esac
+case "$sha12" in .) sha12=file-not-in-blob-but-in-the-working-tree ;; esac
+case "$mode1" in .) mode1=;; *) mode1=" ($mode1)" ;;esac
+case "$mode2" in .) mode2=;; *) mode2=" ($mode2)" ;;esac
+
+diff -pu -L "$sha11/$name$mode1" -L "$sha12/$name$mode2" "$name1" "$name2"
--- k/show-diff.c
+++ l/show-diff.c
@@ -53,14 +53,11 @@ int main(int argc, char **argv)
 		perror("read_cache");
 		exit(1);
 	}
-	prepare_diff_cmd();
+
 	for (i = 0; i < entries; i++) {
 		struct stat st;
 		struct cache_entry *ce = active_cache[i];
 		int changed;
-		unsigned long size;
-		char type[20];
-		void *old;
 
 		if (1 < argc &&
 		    ! matches_pathspec(ce, argv+1, argc-1))
@@ -87,8 +84,7 @@ int main(int argc, char **argv)
 			else {
 				printf("%s: %s\n", ce->name, strerror(errno));
 				if (errno == ENOENT)
-					show_diff_empty(ce->sha1, ce->name,
-							reverse);
+					show_diff_empty(ce, reverse);
 			}
 			continue;
 		}
@@ -104,14 +100,7 @@ int main(int argc, char **argv)
 		if (silent)
 			continue;
 
-		old = read_sha1_file(ce->sha1, type, &size);
-		if (! old)
-			error("unable to read blob object for %s (%s)",
-			      ce->name, sha1_to_hex(ce->sha1));
-		else
-			show_differences(ce->name, ce->name, old, size,
-					 reverse);
-		free(old);
+		show_differences(ce, reverse);
 	}
 	return 0;
 }


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox