Skip to content

Commit 3bc7f9b

Browse files
committed
Fix explicit permissions in DEB and RPM packages
1 parent ace0f92 commit 3bc7f9b

File tree

5 files changed

+184
-15
lines changed

5 files changed

+184
-15
lines changed

src/main/groovy/com/netflix/gradle/plugins/deb/DebCopyAction.groovy

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,22 @@ class DebCopyAction extends AbstractPackagingCopyAction<Deb> {
121121
String group = lookup(specToLookAt, 'permissionGroup') ?: task.permissionGroup
122122
Integer gid = (Integer) lookup(specToLookAt, 'gid') ?: task.gid ?: 0
123123

124-
int fileMode = FilePermissionUtil.getUnixPermission(fileDetails)
124+
// Priority system: explicit permissions take precedence over filesystem detection
125+
Integer explicitMode = FilePermissionUtil.getFileMode(specToLookAt)
126+
int workaroundMode = FilePermissionUtil.getUnixPermission(fileDetails)
127+
128+
logger.debug("File: ${fileDetails.relativePath.pathString}, explicitMode: ${explicitMode}, workaroundMode: ${workaroundMode}")
129+
130+
int fileMode
131+
if (explicitMode != null) {
132+
// We have detected truly explicit permissions - use them
133+
fileMode = explicitMode
134+
logger.debug("Using explicit permissions: ${explicitMode}")
135+
} else {
136+
// Use workaround when no explicit permissions detected
137+
fileMode = workaroundMode
138+
logger.debug("No explicit permissions, using workaround: ${workaroundMode}")
139+
}
125140

126141
debFileVisitorStrategy.addFile(fileDetails, inputFile, user, uid, group, gid, fileMode)
127142
}
@@ -138,7 +153,10 @@ class DebCopyAction extends AbstractPackagingCopyAction<Deb> {
138153
Integer gid = (Integer) lookup(specToLookAt, 'gid') ?: task.gid ?: 0
139154
Boolean setgid = lookup(specToLookAt, 'setgid')
140155

141-
int dirMode = FilePermissionUtil.getUnixPermission(dirDetails)
156+
// Priority system for directories - same as files
157+
Integer explicitDirMode = FilePermissionUtil.getDirMode(specToLookAt)
158+
159+
int dirMode = explicitDirMode != null ? explicitDirMode : FilePermissionUtil.getUnixPermission(dirDetails)
142160
if (setgid == null) {
143161
setgid = task.setgid
144162
}

src/main/groovy/com/netflix/gradle/plugins/rpm/RpmCopyAction.groovy

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,22 @@ class RpmCopyAction extends AbstractPackagingCopyAction<Rpm> {
160160
String user = lookup(specToLookAt, 'user') ?: task.user
161161
String group = lookup(specToLookAt, 'permissionGroup') ?: task.permissionGroup
162162

163-
int fileMode = FilePermissionUtil.getFileMode(specToLookAt) ?: FilePermissionUtil.getUnixPermission(fileDetails)
163+
// Priority system: explicit permissions take precedence over filesystem detection
164+
Integer explicitMode = FilePermissionUtil.getFileMode(specToLookAt)
165+
int workaroundMode = FilePermissionUtil.getUnixPermission(fileDetails)
166+
167+
logger.debug("File: ${fileDetails.relativePath.pathString}, explicitMode: ${explicitMode}, workaroundMode: ${workaroundMode}")
168+
169+
int fileMode
170+
if (explicitMode != null) {
171+
// We have detected truly explicit permissions - use them
172+
fileMode = explicitMode
173+
logger.debug("Using explicit permissions: ${explicitMode}")
174+
} else {
175+
// Use workaround when no explicit permissions detected
176+
fileMode = workaroundMode
177+
logger.debug("No explicit permissions, using workaround: ${workaroundMode}")
178+
}
164179
def specAddParentsDir = lookup(specToLookAt, 'addParentDirs')
165180
boolean addParentsDir = specAddParentsDir != null ? specAddParentsDir : task.addParentDirs
166181

@@ -181,7 +196,11 @@ class RpmCopyAction extends AbstractPackagingCopyAction<Rpm> {
181196

182197
if (createDirectoryEntry) {
183198
logger.debug 'adding directory {}', dirDetails.relativePath.pathString
184-
int dirMode = FilePermissionUtil.getDirMode(specToLookAt) ?: FilePermissionUtil.getUnixPermission(dirDetails)
199+
200+
// Priority system for directories - same as files
201+
Integer explicitDirMode = FilePermissionUtil.getDirMode(specToLookAt)
202+
203+
int dirMode = explicitDirMode != null ? explicitDirMode : FilePermissionUtil.getUnixPermission(dirDetails)
185204
Directive directive = (Directive) lookup(specToLookAt, 'fileType') ?: task.fileType
186205
String user = lookup(specToLookAt, 'user') ?: task.user
187206
String group = lookup(specToLookAt, 'permissionGroup') ?: task.permissionGroup

src/main/groovy/com/netflix/gradle/plugins/utils/FilePermissionUtil.groovy

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ class FilePermissionUtil {
3030
* @return Unix permission as integer (e.g., 0755, 0644)
3131
*/
3232
static int getUnixPermission(FileCopyDetails details) {
33-
3433
int newApiMode = details.permissions.toUnixNumeric()
3534

3635
// Gradle 9.0 permissions API may not detect executable bits correctly
@@ -62,33 +61,64 @@ class FilePermissionUtil {
6261
* @param details
6362
* @return
6463
*/
65-
static Integer getFileMode(SyncSpec copySpecInternal) {
64+
static Integer getFileMode(def copySpecInternal) {
6665
if(!copySpecInternal) {
6766
return null
6867
}
6968

70-
if(copySpecInternal.filePermissions.present){
71-
copySpecInternal.filePermissions.get().toUnixNumeric()
72-
} else {
73-
return null
69+
try {
70+
if(copySpecInternal?.hasProperty('filePermissions') && copySpecInternal.filePermissions?.present) {
71+
def permissions = copySpecInternal.filePermissions.get()
72+
def numeric = permissions.toUnixNumeric()
73+
74+
// Try to detect if this copySpec has explicit configuration (includes, excludes, etc.)
75+
def hasExplicitConfiguration = false
76+
try {
77+
// Look for signs of explicit configuration
78+
if (copySpecInternal.hasProperty('includes') && copySpecInternal.includes?.size() > 0) {
79+
hasExplicitConfiguration = true
80+
}
81+
if (copySpecInternal.hasProperty('excludes') && copySpecInternal.excludes?.size() > 0) {
82+
hasExplicitConfiguration = true
83+
}
84+
} catch (Exception e) {
85+
// Ignore - could not check explicit configuration
86+
}
87+
88+
// If we have explicit configuration OR the permission is not default 644, treat as explicit
89+
if (hasExplicitConfiguration || numeric != 420) {
90+
return numeric
91+
} else {
92+
// Default 644 with no explicit configuration - treat as default
93+
return null
94+
}
95+
}
96+
} catch (Exception e) {
97+
// Ignore - not a proper SyncSpec or permissions not set
7498
}
99+
return null
75100
}
76101

77102
/**
78103
* Get the unix permission of a directory.
79104
* @param copySpecInternal
80105
* @return
81106
*/
82-
static Integer getDirMode(SyncSpec copySpecInternal) {
107+
static Integer getDirMode(def copySpecInternal) {
83108
if(!copySpecInternal) {
84109
return null
85110
}
86111

87-
if(copySpecInternal.dirPermissions.present){
88-
copySpecInternal.dirPermissions.get().toUnixNumeric()
89-
} else {
90-
return null
112+
try {
113+
// Check if dirPermissions was explicitly configured
114+
// This detects the presence of a dirPermissions { } block
115+
if(copySpecInternal?.hasProperty('dirPermissions') && copySpecInternal.dirPermissions?.present){
116+
return copySpecInternal.dirPermissions.get().toUnixNumeric()
117+
}
118+
} catch (Exception e) {
119+
// Ignore - not a proper SyncSpec or permissions not set
91120
}
121+
return null
92122
}
93123

94124
/**

src/test/groovy/com/netflix/gradle/plugins/deb/DebPluginTest.groovy

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,52 @@ class DebPluginTest extends ProjectSpec {
254254

255255
}
256256

257+
def 'explicit permissions override filesystem detection'() {
258+
given:
259+
File srcDir = new File(projectDir, 'src')
260+
srcDir.mkdirs()
261+
262+
// Create executable file
263+
def scriptFile = new File(srcDir, 'script.sh')
264+
FileUtils.writeStringToFile(scriptFile, '#!/bin/bash\necho "test"')
265+
scriptFile.setExecutable(true, false)
266+
267+
// Create regular file
268+
def dataFile = new File(srcDir, 'data.txt')
269+
FileUtils.writeStringToFile(dataFile, 'test data')
270+
dataFile.setExecutable(false, false)
271+
272+
project.apply plugin: 'com.netflix.nebula.deb'
273+
274+
when:
275+
Deb debTask = project.task('buildDeb', type: Deb) {
276+
packageName = 'explicit-permissions-test'
277+
from(srcDir) {
278+
// Override executable script to be non-executable
279+
include 'script.sh'
280+
filePermissions {
281+
unix(0644)
282+
}
283+
}
284+
from(srcDir) {
285+
// Override non-executable file to be executable
286+
include 'data.txt'
287+
filePermissions {
288+
unix(0755)
289+
}
290+
}
291+
}
292+
debTask.copy()
293+
294+
then:
295+
File debFile = debTask.archiveFile.get().asFile
296+
def scan = new Scanner(debFile)
297+
298+
// Explicit permissions should override filesystem detection
299+
0644 == scan.getEntry('./script.sh').mode // Explicitly set to non-executable
300+
0755 == scan.getEntry('./data.txt').mode // Explicitly set to executable
301+
}
302+
257303
def 'specify complete maintainer scripts'() {
258304
given:
259305
project.version = 1.0

src/test/groovy/com/netflix/gradle/plugins/rpm/RpmPluginIntegrationTest.groovy

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,4 +529,60 @@ buildRpm {
529529
true | 1444
530530
false | 0644
531531
}
532+
533+
def 'explicit permissions override filesystem detection'() {
534+
given:
535+
// Create test files with specific filesystem permissions
536+
File srcDir = new File(projectDir, 'src')
537+
srcDir.mkdirs()
538+
539+
// Create an executable script
540+
File scriptFile = new File(srcDir, 'script.sh')
541+
scriptFile.text = '#!/bin/bash\necho "Hello World"'
542+
scriptFile.setExecutable(true, false)
543+
544+
// Create a non-executable data file
545+
File dataFile = new File(srcDir, 'data.txt')
546+
dataFile.text = 'Some data content'
547+
dataFile.setExecutable(false, false)
548+
549+
buildFile << """
550+
plugins {
551+
id 'com.netflix.nebula.rpm'
552+
}
553+
554+
version = '1.0.0'
555+
556+
task buildRpm(type: com.netflix.gradle.plugins.rpm.Rpm) {
557+
packageName = 'explicit-permissions-test'
558+
from('src') {
559+
// Override executable script to be non-executable
560+
include 'script.sh'
561+
filePermissions {
562+
unix(0644)
563+
}
564+
}
565+
from('src') {
566+
// Override non-executable file to be executable
567+
include 'data.txt'
568+
filePermissions {
569+
unix(0755)
570+
}
571+
}
572+
}
573+
"""
574+
575+
when:
576+
runTasks('buildRpm')
577+
578+
then:
579+
def rpmFile = file('build/distributions/explicit-permissions-test-1.0.0.noarch.rpm')
580+
def scanFiles = Scanner.scan(rpmFile).files
581+
def scriptEntry = scanFiles.find { it.name == './script.sh' }
582+
def dataEntry = scanFiles.find { it.name == './data.txt' }
583+
584+
// Explicit permissions should override filesystem detection
585+
scriptEntry.permissions == 0644 // Explicitly set to non-executable
586+
dataEntry.permissions == 0755 // Explicitly set to executable
587+
}
532588
}

0 commit comments

Comments
 (0)