Skip to content
This repository has been archived by the owner on Aug 13, 2024. It is now read-only.

Commit

Permalink
Added force flag (closes #141)
Browse files Browse the repository at this point in the history
  • Loading branch information
chuwy committed Mar 28, 2016
1 parent f3c2da3 commit ca151d9
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 14 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ You can also specify Redshift Schema for your table. For non-raw mode ``atomic``
$ ./schema-guru-0.5.0 ddl --raw --schema business {{input}}
```

Some users are not full rely on Schema Guru JSON Schema derivation or DDL generation and edit their DDLs manually.
By default, Schema Guru will not override your files (either DDLs and migrations) if user made any significant changes (comments and whitespaces are not significant).
Instead Schema Guru will just warn user that file has been changed manually.
To change this behaviour you may specify ``--force`` flag.

```bash
$ ./schema-guru-0.6.0 ddl --force {{input}}
```


### Web UI

You can access our hosted demo of the Schema Guru web UI at [schemaguru.snplowanalytics.com] [webui-hosted]. To run it locally:
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/com.snowplowanalytics/schemaguru/Common.scala
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ object Common {
*
* @return validation with success or error message
*/
def write: Validation[String, String] =
writeToFile(file.getName, file.getParentFile.getAbsolutePath, content)
def write(force: Boolean = false): Validation[String, String] =
writeToFile(file.getName, file.getParentFile.getAbsolutePath, content, force)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ import Common.SchemaVer
*/
trait SchemaGuruCommand

/**
* Command container was created due unability of scopt create
* subcommands with different case classes configurations
* It also contain shorthand-methods
*
* @param command one of required subcommands
*/
case class CommandContainer(command: Option[SchemaGuruCommand] = None) {

// Common
Expand Down Expand Up @@ -132,4 +139,10 @@ case class CommandContainer(command: Option[SchemaGuruCommand] = None) {
case Some(ddl: DdlCommand) => Some(ddl.copy(noHeader = flag))
case other => other
}

def setForce(flag: Boolean): Option[SchemaGuruCommand] =
command match {
case Some(ddl: DdlCommand) => Some(ddl.copy(force = flag))
case other => other
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package com.snowplowanalytics.schemaguru
package cli

// Scala
import scala.language.implicitConversions

// Scalaz
Expand Down Expand Up @@ -45,7 +46,8 @@ case class DdlCommand private[cli] (
schema: Option[String] = None,
varcharSize: Int = 4096,
splitProduct: Boolean = false,
noHeader: Boolean = false) extends SchemaGuruCommand {
noHeader: Boolean = false,
force: Boolean = false) extends SchemaGuruCommand {

import DdlCommand._

Expand Down Expand Up @@ -240,17 +242,17 @@ case class DdlCommand private[cli] (
result.ddls
.map(_.setBasePath("sql"))
.map(_.setBasePath(output.getAbsolutePath))
.map(_.write).map(printMessage)
.map(_.write(force)).map(printMessage)

result.jsonPaths
.map(_.setBasePath("jsonpaths"))
.map(_.setBasePath(output.getAbsolutePath))
.map(_.write).map(printMessage)
.map(_.write(force)).map(printMessage)

result.migrations
.map(_.setBasePath("sql"))
.map(_.setBasePath(output.getAbsolutePath))
.map(_.write).map(printMessage)
.map(_.write(force)).map(printMessage)

result.warnings.map(printMessage)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ object Parser {
action { (_, c) => c.copy(command = c.setNoHeader(true)) }
text "Do not place header comments into output DDL",

opt[Unit]("force")
action { (_, c) => c.copy(command = c.setForce(true)) }
text "Force override existing manually-edited files",

checkConfig {
case CommandContainer(Some(command: DdlCommand))
if !command.input.exists() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ package com.snowplowanalytics.schemaguru
package utils

// Java
import java.io.{ PrintWriter, File }
import java.io.{ IOException, PrintWriter, File }

// Scala
import scala.io.Source

// Scalaz
import scalaz._
Expand All @@ -24,6 +27,38 @@ import Scalaz._
* Utilities for printing and reading to/from files
*/
object FileUtils {
/**
* Check if file has changed content
* All lines changed starting with -- (SQL comment) or blank lines
* are ignored
*
* @param file existing file to check
* @param content new content
* @return true if file has different content or unavailable
*/
def isNewContent(file: File, content: String): Boolean = {
try {
val oldContent = Source.fromFile(file)
.getLines()
.map(_.trim)
.filterNot(_.isEmpty)
.filterNot(_.startsWith("--"))
.toList

val newContent = content
.split("\n")
.map(_.trim)
.filterNot(_.isEmpty)
.filterNot(_.startsWith("--"))
.toList

oldContent != newContent

} catch {
case e: IOException => true
}
}

/**
* Creates a new file with the contents of the list inside.
*
Expand All @@ -32,19 +67,27 @@ object FileUtils {
* @param content Content of file
* @return a success or failure string about the process
*/
def writeToFile(fileName: String, fileDir: String, content: String): Validation[String, String] = {
def writeToFile(fileName: String, fileDir: String, content: String, force: Boolean = false): Validation[String, String] = {
val path = fileDir + "/" + fileName
try {
makeDir(fileDir) match {
case true => {
// Attempt to open the file...
val file = new File(path)

// Print the contents of the list to the new file...
printToFile(file) { _.println(content) }

// Output a success message
s"File [${file.getAbsolutePath}] was written successfully!".success
lazy val contentChanged = isNewContent(file, content)
if (!file.exists()) {
// Print the contents of the list to the new file...
printToFile(file)(_.println(content))
// Output a success message
s"File [${file.getAbsolutePath}] was written successfully!".success
} else if (file.exists() && contentChanged && !force) {
s"File [${file.getAbsolutePath}] already exists and probably was modified manually. You can use --force to override".failure
} else if (contentChanged && force) {
printToFile(file)(_.println(content))
s"File [${file.getAbsolutePath}] was overriden successfully!".success
} else {
s"File [${file.getAbsolutePath}] was not modified".success
}
}
case false => s"Could not make new directory to store files in - Check write permissions".failure
}
Expand Down

0 comments on commit ca151d9

Please sign in to comment.