From 946dd618ab4d80bf83525260385f19a8fba3eb2d Mon Sep 17 00:00:00 2001 From: Emanuel Guerrero Date: Thu, 26 Oct 2017 04:53:44 -0400 Subject: [PATCH] Added read and write methods --- CONTRIBUTING.md | 91 +++++++++++++++++++++++++ Package.swift | 13 ++-- README.md | 60 ++++++++++++++++ Sources/SwiftEnv-C/SwiftEnv.c | 0 Sources/SwiftEnv-C/include/SwiftEnv.h | 25 +++++++ Sources/SwiftEnv/SwiftEnv.swift | 89 +++++++++++++++++++++++- Tests/LinuxMain.swift | 22 ++++++ Tests/SwiftEnvTests/SwiftEnvTests.swift | 91 ++++++++++++++++++++++--- 8 files changed, 374 insertions(+), 17 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 Sources/SwiftEnv-C/SwiftEnv.c create mode 100644 Sources/SwiftEnv-C/include/SwiftEnv.h diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6efd236 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,91 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, +email, or any other method with the owners of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure that the project can be complied and run both macOS and Swift Package Manager. +2. Update the README.md with details of changes to the interface, this includes new environment + variables, exposed ports, useful file locations and container parameters. +3. Increase the version numbers in any examples files and the README.md to the new version that this + Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). +4. Pull Requests will be merged once you have the sign-off from main owners, or if you + do not have permission to do that, you may request the reviewer to merge it for you. + +## Code of Conduct + +### Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +### Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +### Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [INSERT EMAIL ADDRESS]. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/Package.swift b/Package.swift index f3a1cfd..7de6367 100644 --- a/Package.swift +++ b/Package.swift @@ -6,21 +6,22 @@ import PackageDescription let package = Package( name: "SwiftEnv", products: [ - // Products define the executables and libraries produced by a package, and make them visible to other packages. .library( name: "SwiftEnv", targets: ["SwiftEnv"]), ], dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), ], targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages which this package depends on. .target( name: "SwiftEnv", - dependencies: []), + dependencies: ["SwiftEnv-C"], + path: "./Sources/SwiftEnv/"), + .target( + name: "SwiftEnv-C", + dependencies: [], + path: "./Sources/SwiftEnv-C/" + ), .testTarget( name: "SwiftEnvTests", dependencies: ["SwiftEnv"]), diff --git a/README.md b/README.md index 4e3caef..664bb82 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,63 @@ An easy to use interface for accessing environment variables with Swift [![Swift Package Manager compatible](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager) [![DUB](https://img.shields.io/dub/l/vibe-d.svg)](https://github.com/eman6576/SwiftEnv/blob/master/LICENSE) [![platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey.svg)]() + +## Installation + +### Swift Package Manager + +You can add this to your `Package.swift` manifest with +```swift +.package(url: "https://github.com/mxcl/PromiseKit.git", from: "1.0.0") +``` + +## Usage + +### Read + +You can read in a value for a enviroment variable using either `valueForEnviromentVariable` or the subscript for syntatic sugar. +```swift +let ENV = SwiftEnv() + +// Optional("Users//") +// Gets value for key `PATH` using method +let path1 = ENV.valueForEnvironmentVariable("PATH") + +// Optional("Users//") +// Gets value for key `PATH` using subscript +let path2 = ENV["PATH"] +``` + +### Write + +You can set a value for an environment variable using either `setValueForEnvironmentVariable` or the subscript for syntatic sugar. +```swift +let ENV = SwiftEnv() + +// Set value for key `BUILD_CONFIGURATION` using method +ENV.setValueForEnvironmentVariable("Debug") + +// Set value for key `BUILD_CONFIGURATION` using subscript +ENV["BUILD_CONFIGURATION"] = "Release" +``` + +### Reset + +You can reset/remove a value for an environment variable using either `removeValueForEnvironmentVariable` or the subscript for syntatic sugar +```swift +let ENV = SwiftEnv() + +// Remove value for key `TEST_MODE` using method +ENV.removeValueForEnvironmentVariable("TEST_MODE") = nil + +// Remove value for key `BUILD_MODE` using method +ENV["BUILD_MODE"] = nil +``` + +## Contributing + +If you would like to contribute, please consult the [contributing guidelines](https://github.com/eman6576/SwiftEnv/blob/master/CONTRIBUTING.md) for details. Also check out the GitHub issues for major milestones/enhancements needed. + +## License + +SwiftEnv is released under the MIT license. [See LICENSE](https://github.com/eman6576/SwiftEnv/blob/master/LICENSE) for details diff --git a/Sources/SwiftEnv-C/SwiftEnv.c b/Sources/SwiftEnv-C/SwiftEnv.c new file mode 100644 index 0000000..e69de29 diff --git a/Sources/SwiftEnv-C/include/SwiftEnv.h b/Sources/SwiftEnv-C/include/SwiftEnv.h new file mode 100644 index 0000000..68dd8d2 --- /dev/null +++ b/Sources/SwiftEnv-C/include/SwiftEnv.h @@ -0,0 +1,25 @@ +//MIT License +// +//Copyright (c) 2017 Manny Guerrero +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files (the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. + +#include + +extern char **environment; \ No newline at end of file diff --git a/Sources/SwiftEnv/SwiftEnv.swift b/Sources/SwiftEnv/SwiftEnv.swift index 811249c..de455bd 100644 --- a/Sources/SwiftEnv/SwiftEnv.swift +++ b/Sources/SwiftEnv/SwiftEnv.swift @@ -1,3 +1,88 @@ -struct SwiftEnv { - var text = "Hello, World!" +//MIT License +// +//Copyright (c) 2017 Manny Guerrero +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files (the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. + +#if os(Linux) + import Glibc +#else + import Darwin +#endif + +import SwiftEnv_C + +/// A class that provides an easy interface for reading and setting environment variables in both OSX and +/// Linux. +public class SwiftEnv { + + // MARK: - Initializers + + /// Initializes an instance of `SwiftEnv`. + public init() {} +} + + +// MARK: - Public Instance Methods +public extension SwiftEnv { + + /// Retrieves an environment variable. + /// + /// - Parameter variableName: A `String` representing the name of the environment variable. + /// - Returns: A `String` representing the value of the environment variable. + func valueForEnvironmentVariable(_ variableName: String) -> String? { + guard let pointer = getenv(variableName) else { return nil } + return String(validatingUTF8: pointer) + } + + /// Sets a value for an environment variable. + /// + /// - Parameters: + /// - name: A `String` representing the name of a environment variable. + /// - value: A `String` representing the value to set. + /// - overwrite: A `Bool` indicating if the value should be overwritten for an existing environment + /// variable. Defaults to `true`. + func setValueForEnvironmentVariable(_ name: String, value: String, overwrite: Bool = true) { + setenv(name, value, overwrite ? 1 : 0) + } + + /// Removes the value for an environment variable. + /// + /// - Parameter variableName: A `String` representing the name of a environment variable. + func removeValueForEnvironmentVariable(_ variableName: String) { + unsetenv(variableName) + } +} + + +// MARK: - Custom Subscript +public extension SwiftEnv { + subscript(key: String) -> String? { + get { + return valueForEnvironmentVariable(key) + } + set(newValue) { + if let value = newValue { + setValueForEnvironmentVariable(key, value: value) + } else { + removeValueForEnvironmentVariable(key) + } + } + } } diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 4c60bc4..d890dca 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1,3 +1,25 @@ +//MIT License +// +//Copyright (c) 2017 Manny Guerrero +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files (the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. + import XCTest @testable import SwiftEnvTests diff --git a/Tests/SwiftEnvTests/SwiftEnvTests.swift b/Tests/SwiftEnvTests/SwiftEnvTests.swift index 1784147..66e55c9 100644 --- a/Tests/SwiftEnvTests/SwiftEnvTests.swift +++ b/Tests/SwiftEnvTests/SwiftEnvTests.swift @@ -1,16 +1,89 @@ +//MIT License +// +//Copyright (c) 2017 Manny Guerrero +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files (the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. + import XCTest @testable import SwiftEnv -class SwiftEnvTests: XCTestCase { - func testExample() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. - XCTAssertEqual(SwiftEnv().text, "Hello, World!") +final class SwiftEnvTests: XCTestCase { + + // MARK: - Private Instance Attributes + private var ENV: SwiftEnv! + + + // MARK: - Setup & Tear Down + override func setUp() { + ENV = SwiftEnv() + super.setUp() } - - + + override func tearDown() { + ENV = nil + super.tearDown() + } + + + // MARK: - Functional Tests + func testValueForEnviromentVariable() { + guard let path1 = ENV.valueForEnvironmentVariable("PATH") else { + XCTFail("Error retrieving enviroment variable with method") + return + } + XCTAssertFalse(path1.isEmpty, "Value should not be empty") + guard let path2 = ENV["PATH"] else { + XCTFail("Error retrieving enviroment variable with subscript") + return + } + XCTAssertFalse(path2.isEmpty, "Value should not be empty") + } + + func testSetValueForEnviromentVariable() { + ENV.setValueForEnvironmentVariable("FULL_HOUSE_DAD", value: "Bob Saget") + guard let fullHouseDad = ENV["FULL_HOUSE_DAD"] else { + XCTFail("Value was never set with method") + return + } + XCTAssertEqual(fullHouseDad, "Bob Saget", "Wrong value was set") + ENV["FULL_HOUSE_UNCLE"] = "Uncle Jesse" + guard let fullHouseUncle = ENV["FULL_HOUSE_UNCLE"] else { + XCTFail("Value was never set with subscript") + return + } + XCTAssertEqual(fullHouseUncle, "Uncle Jesse", "Wrong value was set") + } + + func testRemoveValueForEnviromentVariable() { + ENV["STAR_WARS_CHARACTER"] = "Luke Skywalker" + guard let _ = ENV["STAR_WARS_CHARACTER"] else { + XCTFail("Value was never set with subscript") + return + } + ENV["STAR_WARS_CHARACTER"] = nil + let starWarsCharacter = ENV["STAR_WARS_CHARACTER"] + XCTAssertNil(starWarsCharacter, "Value should be nil") + } + + + // MARK: - Test Methods static var allTests = [ - ("testExample", testExample), + ("testValueForEnviromentVariable", testValueForEnviromentVariable), ] }