1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
Description: Fix reproducibility issues with autogsdoc.
Forwarded: not-needed
Author: Yavor Doganov <yavor@gnu.org>
Last-Update: 2025-02-19
---
--- gnustep-base.orig/Tools/AGSOutput.m
+++ gnustep-base/Tools/AGSOutput.m
@@ -76,6 +76,19 @@
return [set characterIsMember: [t characterAtIndex: [t length] - 1]];
}
+static NSString *
+debuser (void)
+{
+ NSString *user;
+
+ if (getenv("DEB_BUILD_ARCH"))
+ user = @"Debian";
+ else
+ user = NSFullUserName();
+
+ return user;
+}
+
/**
* <unit>
* <heading>The AGSOutput class</heading>
@@ -426,7 +439,7 @@
authors = [info objectForKey: @"authors"];
if (authors == nil)
{
- tmp = [NSString stringWithFormat: @"Generated by %@", NSFullUserName()];
+ tmp = [NSString stringWithFormat: @"Generated by %@", debuser()];
[str appendString: @" <author name=\""];
[str appendString: tmp];
[str appendString: @"\"></author>\n"];
@@ -2407,7 +2420,7 @@
[str appendString: kind];
[str appendString: @"</title>\n"];
tmp = [NSString stringWithFormat: @"Generated by %@",
- NSFullUserName()];
+ debuser()];
[str appendString: @" <author name=\""];
[str appendString: tmp];
[str appendString: @"\"></author>\n"];
--- gnustep-base.orig/Tools/AGSParser.m
+++ gnustep-base/Tools/AGSParser.m
@@ -27,10 +27,12 @@
#import "Foundation/NSDictionary.h"
#import "Foundation/NSEnumerator.h"
#import "Foundation/NSException.h"
+#import "Foundation/NSFileHandle.h"
#import "Foundation/NSFileManager.h"
#import "Foundation/NSUserDefaults.h"
#import "Foundation/NSScanner.h"
#import "Foundation/NSSet.h"
+#import "Foundation/NSTask.h"
#import "Foundation/NSValue.h"
#import "AGSParser.h"
#import "GNUstepBase/NSString+GNUstepBase.h"
@@ -38,6 +40,84 @@
#define ENDBRACE 0x7D // '}' character
+@interface NSDate (Debian)
++ (instancetype) debianDate;
+@end
+
+@implementation NSDate (Debian)
+
+/* Extract the timestamp from debian/changelog. Return current date
+ (as upstream code does) if something goes wrong. */
++ (instancetype) debianDate
+{
+ NSFileManager *mgr;
+ NSString *timestamp = nil;
+ NSString *curDir;
+ NSString *debDir;
+ BOOL isDir;
+ BOOL ok = YES;
+ int depth = 5;
+
+ if (!getenv("DEB_BUILD_ARCH"))
+ return [NSDate date];
+
+ mgr = [NSFileManager defaultManager];
+ curDir = [mgr currentDirectoryPath];
+ debDir = [curDir stringByAppendingPathComponent: @"debian"];
+
+ /* Determine the toplevel directory; otherwise dpkg-parsechangelog
+ is doomed to fail. Sometimes autogsdoc is invoked from the
+ toplevel (gnustep-sqlclient), sometimes one level below
+ (gnustep-base, gnustep-gui) but it can be deeper (steptalk). */
+ while (!([mgr fileExistsAtPath: debDir isDirectory: &isDir] && isDir)
+ && depth > 0)
+ {
+ curDir = [curDir stringByDeletingLastPathComponent];
+ debDir = [curDir stringByAppendingPathComponent: @"debian"];
+ depth--;
+ }
+
+ NS_DURING
+ {
+ NSTask *task = [NSTask new];
+ NSPipe *pipe = [NSPipe pipe];
+ NSFileHandle *handle;
+ NSData *data;
+
+ [task setLaunchPath: @"dpkg-parsechangelog"];
+ [task setArguments: [NSArray arrayWithObjects: @"-S", @"Timestamp", nil]];
+ [task setCurrentDirectoryPath: curDir];
+ [task setStandardOutput: pipe];
+
+ [task launch];
+ [task waitUntilExit];
+ [task terminate];
+ NSAssert(![task terminationStatus], @"dpkg-parsechangelog failed");
+ DESTROY(task);
+
+ handle = [pipe fileHandleForReading];
+ data = [handle readDataToEndOfFile];
+ timestamp
+ = AUTORELEASE([[NSString alloc] initWithData: data
+ encoding: NSUTF8StringEncoding]);
+ timestamp = [timestamp stringByTrimmingCharactersInSet:
+ [NSCharacterSet newlineCharacterSet]];
+ NSAssert([timestamp length],
+ @"No timestamp obtained from debian/changelog");
+ }
+ NS_HANDLER
+ {
+ NSLog(@"Problem occurred in +debianDate: %@", [localException reason]);
+ ok = NO;
+ }
+ NS_ENDHANDLER
+
+ return ok ? [NSDate dateWithTimeIntervalSince1970: [timestamp floatValue]]
+ : [NSDate date];
+}
+
+@end
+
/**
* The AGSParser class parses Objective-C header and source files
* to produce a property-list which can be handled by [AGSOutput].
@@ -2406,7 +2486,7 @@
if (nil == generated)
{
generated = [[NSString alloc] initWithFormat:
- @"<date>Generated at %@</date>", [NSDate date]];
+ @"<date>Generated at %@</date>", [NSDate debianDate]];
}
[info setObject: generated forKey: @"date"];
}
|