From b148d54000da8d718f95917f8bf805860a6cbfe6 Mon Sep 17 00:00:00 2001 From: Szabolcs Vasas Date: Mon, 23 Jul 2018 13:48:22 +0200 Subject: [PATCH] SQOOP-3052: Introduce Gradle based build for Sqoop to make it more developer friendly / open (Anna Szonyi via Szabolcs Vasas) --- .gitignore | 5 + COMPILING.txt | 57 ++- build.gradle | 400 +++++++++++++++++++ config/checkstyle/checkstyle-java-header.txt | 17 + config/checkstyle/checkstyle-noframes.xsl | 198 +++++++++ config/checkstyle/checkstyle.xml | 226 +++++++++++ gradle.properties | 57 +++ gradle/customUnixStartScript.txt | 100 +++++ gradle/customWindowsStartScript.txt | 26 ++ gradle/sqoop-package.gradle | 209 ++++++++++ gradle/sqoop-version-gen.gradle | 76 ++++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54333 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 ++++++++ gradlew.bat | 84 ++++ settings.gradle | 18 + src/scripts/rat-violations.sh | 4 + testdata/hcatalog/conf/hive-site.xml | 2 +- 18 files changed, 1639 insertions(+), 17 deletions(-) create mode 100644 build.gradle create mode 100644 config/checkstyle/checkstyle-java-header.txt create mode 100644 config/checkstyle/checkstyle-noframes.xsl create mode 100644 config/checkstyle/checkstyle.xml create mode 100644 gradle.properties create mode 100644 gradle/customUnixStartScript.txt create mode 100644 gradle/customWindowsStartScript.txt create mode 100644 gradle/sqoop-package.gradle create mode 100644 gradle/sqoop-version-gen.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore index 68cbe2873..36f53f9af 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,8 @@ target /conf/managers.d /conf/tools.d /tags +src/java/org/apache/sqoop/SqoopVersion.java +gradle/build +gradle/.gradle +.gradle +out diff --git a/COMPILING.txt b/COMPILING.txt index 3b8225048..9abf0b211 100644 --- a/COMPILING.txt +++ b/COMPILING.txt @@ -27,7 +27,7 @@ under the License. Compiling Sqoop requires the following tools: -* Apache ant (1.7.1) +* Apache ant (1.7.1) or Gradle (3.5.1) * Java JDK 1.6 Additionally, building the documentation requires these tools: @@ -52,7 +52,7 @@ Sqoop is compiled with ant. Type +ant -p+ to see the list of available targets. Type +ant+ to compile all java sources. You can then run Sqoop with +bin/sqoop+. If you want to build everything (including the documentation), type -+ant package+. This will appear in the ++ant package+ or +./gradlew package+. This will appear in the +build/sqoop-(version)/+ directory. This version of Sqoop is built against Hadoop 0.23 available from Apache @@ -61,7 +61,7 @@ downloads the necessary binaries. == Testing Sqoop -Sqoop has several unit tests which can be run with +ant test+. This command +Sqoop has several unit tests which can be run with +ant test+ or +./gradlew test+. This command will run all the "basic" checks against an in-memory database, HSQLDB. Sqoop also has compatibility tests that check its ability to work with @@ -203,6 +203,7 @@ After the third-party databases are installed and configured, run: ++++ ant test -Dthirdparty=true -Dsqoop.thirdparty.lib.dir=/path/to/jdbc/drivers/ +./gradlew -Dsqoop.thirdparty.lib.dir=/relative/path/to/jdbc/drivers/ thirdPartyTest ++++ This command will run all thirdparty tests except some DB2 tests. @@ -211,6 +212,7 @@ as follows: ++++ ant test -Dmanual=true -Dsqoop.thirdparty.lib.dir=/path/to/jdbc/drivers/ +./gradlew -Dsqoop.thirdparty.lib.dir=/relative/path/to/jdbc/drivers/ manualTest ++++ Note that +sqoop.thirdparty.lib.dir+ can also be specified in @@ -308,13 +310,15 @@ run: ++++ ant findbugs -Dfindbugs.home=/path/to/findbugs/ +or +./gradlew findbugsMain ++++ A report will be generated in +build/findbugs/+ -=== Cobertura +=== Code Coverage reports -Cobertura runs code coverage checks. It instruments the build and +For ant Cobertura runs code coverage checks. It instruments the build and checks that each line and conditional expression is evaluated along all possible paths. @@ -325,6 +329,19 @@ ant clean ant cobertura -Dcobertura.home=/path/to/cobertura ant cobertura -Dcobertura.home=/path/to/cobertura \ -Dthirdparty=true -Dsqoop.thirdparty.lib.dir=/path/to/thirdparty + +For Gradle we run Jacoco for code coverage checks. You can create single reports or composite reports, +where you can check the combined coverage of unit and thirdparty tests. + +./gradlew clean +./gradlew test +./gradlew jacocoTestReport + +./gradlew -Dsqoop.thirdparty.lib.dir= thirdPartyTest +./gradlew jacocoThirdPartyReport + +or generate the composite report after running test and thirdPartyTest +./gradlew jacocoCompositeReport ++++ (You'll need to run the cobertura target twice; once against the regular @@ -350,6 +367,7 @@ To run checkstyle, execute: ++++ ant checkstyle +./gradlew checkStyleMain ++++ A report will be generated as +build/checkstyle-errors.html+ @@ -364,6 +382,7 @@ To install Sqoop in your local +.m2+ cache, run: ++++ ant mvn-install +./gradlew publishToMavenLocal ++++ This will install a pom and the Sqoop jar. @@ -372,6 +391,8 @@ To deploy Sqoop to a public repository, use: ++++ ant mvn-deploy +./gradlew publishSqoopPublicationToCloudera.snapshot.repoRepository +./gradlew -DmvnRepo=x publishSqoopPublicationToCloudera.x.repoRepository ++++ By default, this deploys to repository.cloudera.com. You can choose @@ -387,7 +408,7 @@ This will build a binary release tarball and the web-based documentation as well as run a release audit which flags any source files which may be missing license headers. -(The release audit can be run standalone with the +ant releaseaudit+ +(The release audit can be run standalone with the +ant releaseaudit+ (+./gradlew rat+) target.) You must set the +version+ property explicitly; you cannot release a @@ -402,16 +423,6 @@ will allow you to edit Sqoop sources in Eclipse with all the library dependencies correctly resolved. To compile the jars, you should still use ant. - -== Using a specific version of Hadoop - -Now Sqoop defaults to use Hadoop 0.23 available from Apache maven repository. -To switch back to the previous version of Hadoop 0.20, for example, run: - -++++ -ant test -Dhadoopversion=20 -++++ - == Building the documentation Building the documentation requires that you have toxml installed. @@ -421,3 +432,17 @@ Also, one needs to set the XML_CATALOG_FILES environment variable. export XML_CATALOG_FILES=/usr/local/etc/xml/catalog ant docs ++++ + +== Other important Gradle commands + ++ Generate gradle wrapper (to ensure you are using the correct, compatible version of gradle) by running +./gradlew wrapper+ ++ ./gradlew tasks to list all top-level gradle tasks or run ./gradlew tasks --all to show all tasks and subtasks ++ ./gradlew compileJava to compile the main Java source ++ ./gradlew -Dsqoop.thirdparty.lib.dir= -Dsqoop.test.mysql.connectstring.host_url=jdbc:mysql://127.0.0.1:3306/ -Dsqoop.test.mysql.databasename=sqoop -Dsqoop.test.mysql.password=Sqoop12345 -Dsqoop.test.mysql.username=sqoop -Dsqoop.test.oracle.connectstring=jdbc:oracle:thin:@//localhost:1521/sqoop -Dsqoop.test.oracle.username=SYSTEM -Dsqoop.test.oracle.password=Sqoop12345 -Dsqoop.test.postgresql.connectstring.host_url=jdbc:postgresql://localhost/ -Dsqoop.test.postgresql.database=sqoop -Dsqoop.test.postgresql.username=sqoop -Dsqoop.test.postgresql.password=Sqoop12345 -Dsqoop.test.cubrid.connectstring.host_url=jdbc:cubrid:localhost:33000 -Dsqoop.test.cubrid.connectstring.username=sqoop -Dsqoop.test.cubrid.connectstring.database=sqoop -Dsqoop.test.cubrid.connectstring.password=Sqoop12345 -Dmapred.child.java.opts="\-Djava.security.egd=file:/dev/../dev/urandom" -Dtest.timeout=10000000 -Dsqoop.test.sqlserver.connectstring.host_url=jdbc:sqlserver://localhost:1433 -Dsqoop.test.sqlserver.database=master -Dms.sqlserver.username=sa -Dms.sqlserver.password=Sqoop12345 -Dsqoop.test.db2.connectstring.host_url=jdbc:db2://localhost:50000 -Dsqoop.test.db2.connectstring.database=SQOOP -Dsqoop.test.db2.connectstring.username=DB2INST1 -Dsqoop.test.db2.connectstring.password=Sqoop12345 thirdPartyTest ++ ./gradlew test --debug-jvm : to run remote debug on port 5005 ++ ./gradlew -Dtest.single=ClassName*Test test or ./gradlew tests --tests ++ To refresh dependencies for a build ./gradlew build --refresh-dependencies ++ For skipping a single test or a set of tests ./gradle build -x test ++ To run a single test class use --tests ClassName*Test or -DtestType.single=ClassName*Test (use with test, thirdPartyTest or manualTest) ++ To get a dependency tree: ./gradlew dependencyInsight --configuration optionalConfiguration --dependency searchedForDependency ++ For a list of the dependencies of the selected project, broken down by configuration run: ./gradlew dependencies \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 000000000..8b8b55575 --- /dev/null +++ b/build.gradle @@ -0,0 +1,400 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +plugins { + id "org.nosphere.apache.rat" version "0.3.0" +} +apply plugin: 'java' +apply plugin: 'eclipse' +apply plugin: 'idea' +apply plugin: 'checkstyle' +apply plugin: 'jacoco' +apply plugin: 'findbugs' +apply plugin: 'maven-publish' + +apply from: 'gradle/sqoop-version-gen.gradle' +apply from: 'gradle/sqoop-package.gradle' + +group = 'org.apache.sqoopgradle' + +sourceCompatibility = javaSourceCompatibilityVersion + +repositories { + mavenCentral() + maven { + url 'http://conjars.org/repo/' + } +} + +sourceSets { + main { + java { + srcDirs = ['src/java'] + } + resources { + srcDirs = ['src/java'] + } + } + test { + java { + srcDirs = ['src/test'] + exclude 'aop/' + } + resources { + srcDirs = ['src/test', 'testdata/hcatalog/conf', 'conf'] + exclude 'aop/' + } + } + aop { + java { + srcDirs = ['src/test/aop'] + } + resources { + srcDirs = ['src/test/aop'] + } + } +} + +configurations { + common.extendsFrom(redist) + compile.extendsFrom(common) +} + +compileJava.dependsOn(SqoopVersionFileGen) + +configurations.all { + resolutionStrategy { + force group: 'org.apache.avro', name: 'avro', version: avroVersion + force group: 'org.apache.avro', name: 'avro-mapred', version: avroVersion + } + exclude group: 'org.apache.hadoop', module: 'avro' +} + +def sqoopThirdPartyLib = System.getProperty("sqoop.thirdparty.lib.dir") + +dependencies { + if (sqoopThirdPartyLib != null) runtime fileTree(dir: sqoopThirdPartyLib, include: '*.jar') + compile group: 'org.apache.hadoop', name: 'hadoop-common', version: hadoopVersion + compile group: 'org.apache.hadoop', name: 'hadoop-hdfs', version: hadoopVersion + compile group: 'org.apache.hadoop', name: 'hadoop-mapreduce-client-common', version: hadoopVersion + compile group: 'org.apache.hadoop', name: 'hadoop-mapreduce-client-core', version: hadoopVersion + compile group: 'org.apache.hbase', name: 'hbase-hadoop-compat', version: hbaseVersion + + aopCompile group: 'org.aspectj', name: 'aspectjtools', version: aspectjVersion + aopCompile group: 'org.aspectj', name: 'aspectjrt', version: aspectjVersion + aopCompile group: 'org.apache.hadoop', name: 'hadoop-common', version: hadoopVersion + + common group: 'org.apache.accumulo', name: 'accumulo-core', version: accumuloVersion + common group: 'org.apache.accumulo', name: 'accumulo-minicluster', version: accumuloVersion + common group: 'org.apache.hbase', name: 'hbase-hadoop2-compat', version: hbaseVersion + common group: 'org.apache.hbase', name: 'hbase-server', version: hbaseVersion + common group: 'org.apache.hbase', name: 'hbase-client', version: hbaseVersion + common group: 'org.apache.hbase', name: 'hbase-common', version: hbaseVersion + common (group: 'org.apache.hive.hcatalog', name: 'hive-hcatalog-core', version: hcatalogVersion) { + exclude group: 'org.apache.avro', module: 'avro' + } + common (group: 'org.apache.hive', name: 'hive-jdbc', version: hcatalogVersion) { + exclude group: 'org.apache.avro', module: 'avro' + } + common group: 'commons-cli', name: 'commons-cli', version: commonscliVersion + common group: 'commons-logging', name: 'commons-logging', version: commonsloggingVersion + common group: 'commons-net', name: 'commons-net', version: commonsnetVersion + common group: 'log4j', name: 'log4j', version: log4jVersion + common group: 'org.postgresql', name: 'postgresql', version: postgresqlVersion + + testCompile group: 'com.h2database', name: 'h2', version: h2Version + testCompile group: 'org.apache.hbase', name: 'hbase-server', version: hbaseVersion, classifier: 'tests' + testCompile group: 'org.apache.hbase', name: 'hbase-hadoop2-compat', version: hbaseVersion, classifier: 'tests' + testCompile group: 'org.apache.hbase', name: 'hbase-hadoop-compat', version: hbaseVersion, classifier: 'tests' + testCompile( group: 'org.apache.hadoop', name: 'hadoop-minikdc', version: hadoopVersion) { + exclude group: 'org.apache.directory.api', module: 'api-ldap-schema-data' + } + testCompile group: 'junit', name: 'junit', version: junitVersion + testCompile group: 'org.assertj', name: 'assertj-core', version: assertjVersion + testCompile group: 'org.mockito', name: 'mockito-core', version: mockitoallVersion + testCompile group: 'org.apache.zookeeper', name: 'zookeeper', version: zookeeperVersion, ext: 'jar' +} + +test { + include '**/Test*.*' +} + +task thirdPartyTest(type: Test) { + description 'Run ThirdParty tests - you need to specify -Dsqoop.thirdparty.lib.dir where the Third party driver jars reside (relative to the project directory)' + exclude '**/*ManualTest.*' + exclude '**/Test*.*' + include '**/*Test*.*' + systemProperty "ms.datatype.test.data.file.export" ,"DatatypeTestData-export-lite.txt" + systemProperty "ms.datatype.test.data.file.import" ,"DatatypeTestData-import-lite.txt" + systemProperty "ms.datatype.test.data.file.delim" ,"," + systemProperty "ms.datatype.test.hdfsprefix" ,"file:///" +} + +task manualTest(type: Test) { + description 'Run manual tests' + include '**/*ManualTest.*' +} + +def testBuildDir = "$buildDir/test/" +def testBuildDirData ="$testBuildDir/data/" + +task buildFolder { + project.mkdir(testBuildDirData) +} + +tasks.withType(Test) { + testLogging { + events 'started', 'passed', 'skipped' + } + workingDir = testBuildDirData + project.mkdir(workingDir) + systemProperties(System.getProperties()) + systemProperty "test.data.dir", "$projectDir/testdata" + systemProperty 'test.build.data', "$testBuildDir/data" + systemProperty "hadoop.root.logger", "DEBUG,console" + systemProperty "user.dir", workingDir + systemProperty "sqoop.src.dir", "$testBuildDir/data" + systemProperty "hadoop.tmp.dir", "$testBuildDir/hadoop" + systemProperty "fs.default.name", "" + systemProperty "hadoop.log.dir", "$testBuildDir/logs" + systemProperty "hive.home", "$projectDir/testdata/hive" + systemProperty "sqoop.throwOnError", "" + + minHeapSize = "512m" + maxHeapSize = "5120m" + jvmArgs '-Xmx5012m', '-XX:PermSize=256m', '-XX:MaxPermSize=512m', "-da:org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge" + forkEvery 1 + + dependsOn buildFolder + + jacoco{ + excludes = ["**/SqoopVersion*"] + } +} + +tasks.withType(Checkstyle) { + reports { + xml.enabled false + html.enabled true + html.stylesheet resources.text.fromFile('config/checkstyle/checkstyle-noframes.xsl') + } + ignoreFailures = true +} + +tasks.withType(FindBugs) { + reports { + xml.enabled false + html.enabled true + } + ignoreFailures = false +} + +findbugs { + sourceSets = [] +} + +checkstyle { + sourceSets = [] + toolVersion checkstyleVersion +} + +jacocoTestReport { + description "Generates a coverage report of the unit test results under $buildDir/jacocoHtml/test/index.html" + reports { + xml.enabled true + csv.enabled false + html.destination "$buildDir/jacocoHtml/test" + } +} + +task jacocoThirdPartyReport(type: JacocoReport){ + description "Generates a coverage report of the thirdparty test results under $buildDir/jacocoHtml/3rd/index.html" + sourceSets sourceSets.main + executionData thirdPartyTest + reports { + xml.enabled true + csv.enabled false + html.destination "$buildDir/jacocoHtml/3rd" + } +} + +task jacocoCompositeReport(type: JacocoReport){ + description "Generates a composite coverage report of test and thirdparty test results under $buildDir/jacocoHtml/index.html" + sourceSets sourceSets.main + executionData test, thirdPartyTest + reports { + xml.enabled true + csv.enabled false + html.destination "$buildDir/jacocoHtml/" + } +} + +javadoc { + source = sourceSets.main.allJava + include 'com/cloudera/sqoop/lib/**' + include 'org/apache/sqoop/lib/**' + destinationDir = reporting.file("${project.docsDir}/api") +} + +task faultInjectionJar(type: Jar) { + description 'Create the test jar' + appendix = 'test' + from sourceSets.aop.output +} + +def archiveName = jar.baseName + "-" + jar.version +def binArtifactName = archiveName + ".bin__hadoop-" + hadoopVersion +def distDir = "$buildDir/$binArtifactName" + +rat { + inputDir = distDir + reportDir = project.file(buildDir) + excludes = ['**/docs/**', '**/testdata/**', '**/.idea/**', '**/test-dir/**', '**/.settings/**', '**/.gradle/**','**/gradle/**' ,'**/gradle/build/**', '*.iml', '*.iws', '*.ipr', 'derby.log', '**/gradlew**' ] + failOnError = true + xmlOutput = false + htmlOutput = true + plainOutput = false +} +rat.dependsOn('packageDist') + +def scripts = ['export', 'list-databases', 'metastore', 'create-hive-table', 'help', + 'import-mainframe', 'list-tables', 'version', + 'eval', 'import', 'job', 'merge', + 'import-all-tables', 'codegen'] + + +task runSqoopHelp(type: JavaExec, dependsOn: 'classes') { + main = 'org.apache.sqoop.Sqoop' + jvmArgs = ['-Dhadoop.security.log.file=./build/security-audit.log'] + classpath = sourceSets.main.runtimeClasspath + configurations.runtime + args = ['help'] + standardOutput = new ByteArrayOutputStream() + ext.helpOut = { + standardOutput.toString() + } + +} + +task createAllStartScripts(dependsOn: 'runSqoopHelp' ) doLast{ + // Placeholder task with validation + // We call Sqoop help to verify that all tasks that we create scripts for are present in Sqoop help and vice-versa + // We currently depend on the format of the help output to parse the relevant information out + def matcher = (tasks.runSqoopHelp.helpOut() =~/(?m)^\s\s([a-z-]+)\s+\w+/) + def matches = new String[matcher.getCount()] + for (def i=0; i < matcher.getCount(); i++) { + matches[i] = matcher[i][1] + } + if (matches.sort() != scripts.sort()) + throw new GradleException('Error: script list in gradle build script and result of Sqoop help are not the same, but should be') +} + +scripts.each() { scriptName -> + def t = tasks.create(name: scriptName + 'StartScript', type: CreateStartScripts) { + unixStartScriptGenerator.template = resources.text.fromFile('gradle/customUnixStartScript.txt') + windowsStartScriptGenerator.template = resources.text.fromFile('gradle/customWindowsStartScript.txt') + outputDir = file("$buildDir/bin") + applicationName = scriptName + mainClassName = 'com.cloudera.sqoop.Sqoop' + classpath = project.configurations.runtime + doLast { + file("$buildDir/bin/"+ scriptName).renameTo(file("$buildDir/bin/"+"sqoop-"+scriptName)) + file("$buildDir/bin/"+ scriptName +".bat").renameTo(file("$buildDir/bin/"+"sqoop-"+scriptName+".bat")) + } + } + t.dependsOn('compileJava') + createAllStartScripts.dependsOn(t) +} + +task checkVersion doLast { + if (version.contains('SNAPSHOT')) + throw new GradleException('Error: cannot release a snapshot. Set -Pversion') +} + +task release(dependsOn: ['checkVersion', 'tar', 'rat']) { + doLast { + println 'Release complete' + println "Binary tar: $buildDir/$binArtifactName-${version}.tar.gz" + println "Documentation: $buildDir/docs" + println "Release notes: $buildDir/docs/sqoop-$version" + ".releasenotes.html" + println "Release audit report: $buildDir/index.html" + } +} + +task relnotes(type: Exec) { + workingDir 'src/scripts' + if (!version.contains('SNAPSHOT')) { + commandLine "python", "relnotes.py", "$buildDir/docs", "$projectDir", "$oldHash\\..HEAD", "$version", "$oldVersion" + } else { + commandLine "true" //noop + println "Will not run releasenotes for SNAPSHOT version." + } +} + +task realDocs(type: Exec, dependsOn: ['relnotes', 'javadoc']) { + workingDir projectDir + commandLine "make", "-C", "$projectDir/src/docs", "BUILDROOT=$buildDir", "VERSION=$version" +} + +task docs(dependsOn: ['realDocs', 'relnotes', 'javadoc']) { + //placeholder +} +def $mvnRepo = System.getProperty("mvnRepo", "snapshots") + +publishing { + repositories { + maven { + name "cloudera." + $mvnRepo + ".repo" + url "https://repository.cloudera.com/content/repositories/"+$mvnRepo + credentials { + username 'username' + password 'password' + } + } + } +} +publishing { + publications { + sqoop(MavenPublication) { + groupId group + version version + from components.java + artifact sourceJar { + classifier "sources" + } + } + sqoopTest(MavenPublication) { + groupId group + version version + artifactId 'sqoop-test' + artifact testJar + artifact sourceTestJar + pom.withXml { + def dependencies = asNode().appendNode('dependencies') + configurations.testRuntime.getResolvedConfiguration().getFirstLevelModuleDependencies().each { + def dependency = dependencies.appendNode('dependency') + dependency.appendNode('groupId', it.moduleGroup) + dependency.appendNode('artifactId', it.moduleName) + dependency.appendNode('version', it.moduleVersion) + } + } + } + } +} + +task wrapper(type: Wrapper) { + gradleVersion = '3.5.1' +} diff --git a/config/checkstyle/checkstyle-java-header.txt b/config/checkstyle/checkstyle-java-header.txt new file mode 100644 index 000000000..5d5f1e35f --- /dev/null +++ b/config/checkstyle/checkstyle-java-header.txt @@ -0,0 +1,17 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/config/checkstyle/checkstyle-noframes.xsl b/config/checkstyle/checkstyle-noframes.xsl new file mode 100644 index 000000000..60175c663 --- /dev/null +++ b/config/checkstyle/checkstyle-noframes.xsl @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

CheckStyle Audit

Designed for use with CheckStyle and Ant.
+
+ + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +

Files

+ + + + + + + + + + + + + + +
NameErrors
+
+ + + + +

File

+ + + + + + + + + + + + + + +
Error DescriptionLine
+ Back to top +
+ + + +

Summary

+ + + + + + + + + + + + +
FilesErrors
+
+ + + + a + b + + +
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 000000000..b7e5143e5 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..a571e6cb2 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,57 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# This properties file lists the versions of the various artifacts we use in gradle. + +javaSourceCompatibilityVersion=1.7 + +avroVersion=1.8.1 +kitedataVersion=1.1.0 +hadoopVersion=2.8.0 +aspectjVersion=1.7.4 +zookeeperVersion=3.4.6 +hbaseVersion=1.2.4 +hcatalogVersion=1.2.1 + +accumuloVersion=1.6.2 + +h2Version=1.3.170 +hsqldbVersion=1.8.0.10 + +commonscliVersion=1.2 +commonscollectionsVersion=3.2.2 +commonsioVersion=1.4 +commonslangVersion=2.4 +commonslang3Version=3.4 +commonsloggingVersion=1.0.4 +commonsnetVersion=3.1 + +log4jVersion=1.2.16 +junitVersion=4.12 +mockitoallVersion=1.9.5 +assertjVersion=2.8.0 + +checkstyleVersion=5.5 + +version=1.5.0-SNAPSHOT + +postgresqlVersion=9.2-1003-jdbc4 + +oldHash=b0f391e75154be86f95378ab141f6dd1b3b59475 +oldVersion=1.4.7 + +org.gradle.daemon=true diff --git a/gradle/customUnixStartScript.txt b/gradle/customUnixStartScript.txt new file mode 100644 index 000000000..702ff69e7 --- /dev/null +++ b/gradle/customUnixStartScript.txt @@ -0,0 +1,100 @@ +#!/bin/bash +# +# Copyright 2011 The Apache Software Foundation +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +follow_one() { + # Resolve symlinks and relative path components along a path. This requires + # its argument to be an absolute path. This does not recursively re-resolve + # symlinks; if that is required, use the 'follow' method. + + target=\$1 + OIFS=\$IFS + IFS='/' + + # Taking each dir component along the way, build up a new target directory, + # resolving '.', '..', and symlinks. + newtarget='' + for part in \${target}; do + if [ -z "\${part}" ]; then + continue # Empty dir part. 'foo//bar' + elif [ "." == "\${part}" ]; then + continue # Nothing special to do for '.' + elif [ ".." == "\${part}" ]; then + IFS=\$OIFS + newtarget=`dirname \${newtarget}` # pop a component. + elif [ -h "\${newtarget}/\${part}" ]; then + IFS=\$OIFS + link=`readlink \${newtarget}/\${part}` + # links can be relative or absolute. Relative ones get appended to + # newtarget; absolute ones replace it. + if [ "\${link:0:1}" != "/" ]; then + newtarget="\${newtarget}/\${link}" # relative + else + newtarget="\${link}" # absolute + fi + else # Regular file component. + newtarget="\${newtarget}/\${part}" + fi + IFS='/' + done + + IFS=\$OIFS + echo \$newtarget +} + +follow() { + # Portable 'readlink -f' function to follow a file's links to the final + # target. Calls follow_one recursively til we're finished tracing symlinks. + + target=\$1 + depth=\$2 + + if [ -z "\$depth" ]; then + depth=0 + elif [ "\$depth" == "1000" ]; then + # Don't recurse indefinitely; we've probably hit a symlink cycle. + # Just bail out here. + echo \$target + return 1 + fi + + # Canonicalize the target to be an absolute path. + targetdir=`dirname \${target}` + targetdir=`cd \${targetdir} && pwd` + target=\${targetdir}/`basename \${target}` + + # Use follow_one to resolve links. Test that we get the same result twice, + # to terminate iteration. + first=`follow_one \${target}` + second=`follow_one \${first}` + if [ "\${first}" == "\${second}" ]; then + # We're done. + echo "\${second}" + else + # Need to continue resolving links. + echo `follow \${second} \$(( \$depth + 1 ))` + fi +} + +prgm=`follow \$0` +bin=`dirname \${prgm}` +bin=`cd \${bin} && pwd` + +exec \${bin}/sqoop ${applicationName} "\$@" diff --git a/gradle/customWindowsStartScript.txt b/gradle/customWindowsStartScript.txt new file mode 100644 index 000000000..57a23f70e --- /dev/null +++ b/gradle/customWindowsStartScript.txt @@ -0,0 +1,26 @@ +@echo off +:: Licensed to the Apache Software Foundation (ASF) under one or more +:: contributor license agreements. See the NOTICE file distributed with +:: this work for additional information regarding copyright ownership. +:: The ASF licenses this file to You under the Apache License, Version 2.0 +:: (the "License"); you may not use this file except in compliance with +:: the License. You may obtain a copy of the License at +:: +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, software +:: distributed under the License is distributed on an "AS IS" BASIS, +:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +:: See the License for the specific language governing permissions and +:: limitations under the License. +setlocal + +set prgm=%~f0 +set bin=%~dp0 + +if "%bin:~-1%" == "\" ( + set bin=%bin:~0,-1% +) + +call "%bin%\\sqoop.cmd" SUBCOMMANDMARKER %* diff --git a/gradle/sqoop-package.gradle b/gradle/sqoop-package.gradle new file mode 100644 index 000000000..076fed858 --- /dev/null +++ b/gradle/sqoop-package.gradle @@ -0,0 +1,209 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +configurations { + redist +} + +dependencies { + redist group: 'commons-io', name: 'commons-io', version: commonsioVersion + redist(group: 'org.apache.avro', name: 'avro', version: avroVersion) { + exclude group: 'org.slf4j', module: 'slf4j-api' + exclude group: 'org.mortbay.jetty', module: 'jetty' + exclude group: 'org.mortbay.jetty', module: 'jetty-util' + exclude group: 'org.mortbay.jetty', module: 'servlet-api' + exclude module: 'netty' + exclude group: 'org.apache.velocity', module: 'velocity' + } + redist(group: 'org.apache.avro', name: 'avro-mapred', version: avroVersion, classifier: 'hadoop2') { + exclude group: 'org.slf4j', module: 'slf4j-api' + exclude group: 'org.mortbay.jetty', module: 'jetty' + exclude group: 'org.mortbay.jetty', module: 'jetty-util' + exclude group: 'org.mortbay.jetty', module: 'servlet-api' + exclude module: 'netty' + exclude group: 'org.apache.velocity', module: 'velocity' + } + redist group: 'hsqldb', name: 'hsqldb', version: hsqldbVersion + redist group: 'org.apache.commons', name: 'commons-lang3', version: commonslang3Version + redist group: 'org.kitesdk', name: 'kite-data-mapreduce', version: kitedataVersion + redist group: 'org.kitesdk', name: 'kite-data-hive', version: kitedataVersion +} + +//Jar tasks +jar { + baseName = rootProject.name.toLowerCase() + destinationDir = buildDir +} + +task testJar(type: Jar) { + baseName = rootProject.name.toLowerCase() + destinationDir = buildDir + description 'Create the test jar' + appendix = 'test' + from sourceSets.test.output +} + +task jarAll(dependsOn: ['testJar', 'jar']) + +def buildSrcJarDir = "$buildDir/srcjars" + +task sourceJar(type: Jar) { + description 'Create source jars' + classifier = 'sources' + from sourceSets.main.allSource + into buildSrcJarDir +} + +task sourceTestJar(type: Jar) { + description 'Create source jars' + classifier = 'sources' + appendix = 'test' + from sourceSets.test.allSource + into buildSrcJarDir +} + +task sourceJars(dependsOn: ['jarAll', 'sourceJar', 'sourceTestJar']) + +//tar tasks +def srcArchiveName =jar.baseName.toLowerCase() + "-" + jar.version +def srcDirstDir = "$buildDir/$srcArchiveName" +def binArtifactName = srcArchiveName + ".bin__hadoop-" + hadoopVersion +def distDir = "$buildDir/$binArtifactName" + +task copyToSrcDistDir(type: Copy) { + from(projectDir) { + include "**/*" + exclude "build/**", ".git/**", "tags", ".project", ".classpath", "conf/managers.d/**", "conf/tools.d/**", ".gradle/**" + } + into srcDirstDir + includeEmptyDirs = false +} + +task filepermissionForSrcDist(type: Exec) { + commandLine 'chmod', 'ugo+x', "$srcDirstDir/bin" + commandLine 'chmod', 'ugo+x', "$srcDirstDir/testdata/hive/bin" + fileTree("$srcDirstDir").matching { include "**/*.sh" }.each { aFile -> + exec { + commandLine 'chmod' + args 'ugo+x', aFile.absolutePath + } + } +} + +task srcPackageDist(dependsOn: ['copyToSrcDistDir', 'filepermissionForSrcDist']) + +task srctar(type: Tar, dependsOn: srcPackageDist) { + from("$srcDirstDir") { + include "**" + exclude "**/*.sh", "testdata/hive/bin/*", "bin/*" + fileMode 0644 + } + from("$srcDirstDir") { + include "**/*.sh", "testdata/hive/bin/*", "bin/*", "testdata/hcatalog/conf/*" + fileMode 0755 + } + baseName = srcArchiveName + destinationDir = file("$buildDir") + extension = 'tar.gz' + compression = Compression.GZIP +} + +task copyToDistDir(type: Copy, dependsOn: ['jarAll', 'docs', 'createAllStartScripts']) { + from jar + from testJar + from(projectDir) { + include "**/*" + exclude "build/**", "lib/**", ".git/**", "tags", ".project", ".classpath", "conf/managers.d/**", "conf/tools.d/**", ".gradle/**" + } + into distDir + includeEmptyDirs = false +} + +task copyToDistLibDir(type: Copy, dependsOn: [configurations.redist, copyToDistDir]) { + from configurations.redist + from("$projectDir/lib") { + include "**/*" + exclude "ivy*" + } + into "$distDir/lib" + includeEmptyDirs = false +} + +task copyToDistDirDocs(type: Copy, dependsOn: ['docs', 'copyToDistLibDir']) { + from("$buildDir/docs") { + include "**/*.html", "**/*.css", "images/**" + } + into "$distDir/docs" + includeEmptyDirs = false +} + +task copyToDistDirDocsMan(type: Copy, dependsOn: ['docs', 'copyToDistDirDocs']) { + from("$buildDir/docs") { + include "**/*.gz" + } + into "$distDir/docs/man" + includeEmptyDirs = false +} + +task copyToDistBinDir(type: Copy, dependsOn: ['copyToDistDirDocsMan']) { + from("$buildDir/bin") { + include "*" + } + into "$distDir/bin" + includeEmptyDirs = false +} + +task filepermissionForDist(type: Exec, dependsOn: ['copyToDistBinDir']) { + commandLine 'chmod', 'ugo+x', "$distDir/bin" + commandLine 'chmod', 'ugo+x', "$distDir/testdata/hive/bin" + fileTree("$distDir").matching { include "**/*.sh" }.each { aFile -> + exec { + commandLine 'chmod' + args 'ugo+x', aFile.absolutePath + } + } +} + +def contentSpec = copySpec { + from("$distDir/conf") { + include "sqoop-site-template.xml" + } + rename('sqoop-site-template.xml', 'sqoop-site.xml') +} + +task copyAndOverwriteSqoopSiteXML(type: Copy, dependsOn: filepermissionForDist) { + into "$distDir/conf" + with contentSpec +} + +task packageDist(dependsOn: ['copyToDistDir', 'copyToDistLibDir', 'copyToDistDirDocs', 'copyToDistDirDocsMan', 'copyToDistBinDir', 'filepermissionForDist', 'copyAndOverwriteSqoopSiteXML']) + +task tar(type: Tar, dependsOn: packageDist) { + from("$buildDir") { + include "$binArtifactName/**" + exclude "$binArtifactName/**/*.sh", "$binArtifactName/testdata/hive/bin/*", "$binArtifactName/bin/*" + fileMode 0644 + } + from("$buildDir") { + include "$binArtifactName/**/*.sh", "$binArtifactName/testdata/hive/bin/*", "$binArtifactName/bin/*", "$binArtifactName/testdata/hcatalog/conf/*" + fileMode 0755 + } + baseName = binArtifactName + destinationDir = file("$buildDir") + extension = 'tar.gz' + compression = Compression.GZIP +} diff --git a/gradle/sqoop-version-gen.gradle b/gradle/sqoop-version-gen.gradle new file mode 100644 index 000000000..2afcea477 --- /dev/null +++ b/gradle/sqoop-version-gen.gradle @@ -0,0 +1,76 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.text.SimpleDateFormat + +def getGitHash = { -> + def stdout = new ByteArrayOutputStream() + exec { + commandLine 'git', 'log', '-1', '--pretty=format:%H' + standardOutput = stdout + } + return stdout.toString().trim() +} +def signature = getGitHash + +def user = System.getProperty("user.name") + +task SqoopVersionFileGen() { + doLast { + def file = new File("$projectDir/src/java/org/apache/sqoop/SqoopVersion.java") + file.createNewFile() + file.text = """ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// generated by gradle task +package org.apache.sqoop; + +public class SqoopVersion { + public SqoopVersion() { + } + + public static final String VERSION="$version"; + public static final String GIT_HASH="$signature"; + public static final String COMPILE_USER="$user"; + public static final String COMPILE_DATE="${new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date())}"; + + @Override + public String toString() { + return "Sqoop " + VERSION + "\\n" + + "git commit id " + GIT_HASH + "\\n" + + "Compiled by " + COMPILE_USER + + " on " + COMPILE_DATE + "\\n"; + } + } +""" + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..99340b4ad18d3c7e764794d300ffd35017036793 GIT binary patch literal 54333 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 D&=%~j literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..90a06cec7 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-bin.zip diff --git a/gradlew b/gradlew new file mode 100755 index 000000000..cccdd3d51 --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 000000000..f9553162f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..7d64af500 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,18 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +rootProject.name ='Sqoop' diff --git a/src/scripts/rat-violations.sh b/src/scripts/rat-violations.sh index 1cfbc1502..9911321f2 100755 --- a/src/scripts/rat-violations.sh +++ b/src/scripts/rat-violations.sh @@ -47,7 +47,11 @@ sed -i -e "s|${basedir}||" ${auditlog} # Anything in /testdata is a file that is supposed to represent exact output. grep '!?????' ${auditlog} \ | grep -v ' \/docs\/' \ + | grep -v ' \/target\/' \ | grep -v ' \/testdata\/' \ + | grep -v ' \/gradle\/' \ + | grep -v ' \/gradlew' \ + | grep -v ' \/gradlew.bat' \ > ${filtered} # Check: did we find any violations after filtering? diff --git a/testdata/hcatalog/conf/hive-site.xml b/testdata/hcatalog/conf/hive-site.xml index edac7aa90..4922abd57 100644 --- a/testdata/hcatalog/conf/hive-site.xml +++ b/testdata/hcatalog/conf/hive-site.xml @@ -34,7 +34,7 @@ javax.jdo.option.ConnectionURL - jdbc:derby:;databaseName=${test.build.data}/sqoop/metastore_db;create=true + jdbc:derby:memory:metastore_db;create=true javax.jdo.option.ConnectionDriverName