diff --git a/.travis.yml b/.travis.yml
index fdf9bd708..979a61bed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,7 +14,7 @@ env:
script:
- make
-- make test GOFLAGS="-race"
+- make test GOFLAGS="-timeout 20m -race -v"
- make coverage
after_success:
diff --git a/Makefile b/Makefile
index 57bdf888e..f9eb341fa 100644
--- a/Makefile
+++ b/Makefile
@@ -107,6 +107,7 @@ spelling:
test: build
@echo "Running all minio testing:"
+ @go test $(GOFLAGS) .
@go test $(GOFLAGS) github.com/minio/minio/cmd...
@go test $(GOFLAGS) github.com/minio/minio/pkg...
diff --git a/README.md b/README.md
index 82b508ecb..1f2540c6c 100644
--- a/README.md
+++ b/README.md
@@ -43,6 +43,8 @@ chmod 755 minio
|GNU/Linux|64-bit Intel|https://dl.minio.io/server/minio/release/linux-amd64/minio|
||32-bit Intel|https://dl.minio.io/server/minio/release/linux-386/minio|
||32-bit ARM|https://dl.minio.io/server/minio/release/linux-arm/minio|
+||64-bit ARM|https://dl.minio.io/server/minio/release/linux-arm64/minio|
+||32-bit ARMv6|https://dl.minio.io/server/minio/release/linux-arm6vl/minio|
```sh
chmod +x minio
./minio server ~/Photos
diff --git a/README_ZH.md b/README_ZH.md
index 8e911a4ae..05d463920 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -11,6 +11,8 @@ Minio是一个非常轻量的服务,可以很简单的和其他应用的结合
|GNU/Linux|64-bit Intel|https://dl.minio.io/server/minio/release/linux-amd64/minio|
||32-bit Intel|https://dl.minio.io/server/minio/release/linux-386/minio|
||32-bit ARM|https://dl.minio.io/server/minio/release/linux-arm/minio|
+||64-bit ARM|https://dl.minio.io/server/minio/release/linux-arm64/minio|
+||32-bit ARMv6|https://dl.minio.io/server/minio/release/linux-arm6vl/minio|
|Apple OS X|64-bit Intel|https://dl.minio.io/server/minio/release/darwin-amd64/minio|
|Microsoft Windows|64-bit|https://dl.minio.io/server/minio/release/windows-amd64/minio.exe|
||32-bit|https://dl.minio.io/server/minio/release/windows-386/minio.exe|
diff --git a/appveyor.yml b/appveyor.yml
index 7488c103a..68a87aa07 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -35,9 +35,9 @@ test_script:
# Unit tests
- ps: Add-AppveyorTest "Unit Tests" -Outcome Running
- mkdir build\coverage
- - go test -timeout 15m -v -race github.com/minio/minio/cmd...
+ - go test -timeout 20m -v -race github.com/minio/minio/cmd...
- go test -v -race github.com/minio/minio/pkg...
- - go test -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd
+ - go test -timeout 15m -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd
- ps: Update-AppveyorTest "Unit Tests" -Outcome Passed
after_test:
diff --git a/browser/README.md b/browser/README.md
index 74bb563f2..647147fdf 100644
--- a/browser/README.md
+++ b/browser/README.md
@@ -4,34 +4,69 @@
## Installation
-### Install yarn:
+### Install yarn
```sh
-$ curl -o- -L https://yarnpkg.com/install.sh | bash
-$ yarn
+curl -o- -L https://yarnpkg.com/install.sh | bash
+yarn
```
-### Install `go-bindata` and `go-bindata-assetfs`.
+### Install `go-bindata` and `go-bindata-assetfs`
If you do not have a working Golang environment, please follow [Install Golang](https://docs.minio.io/docs/how-to-install-golang)
```sh
-$ go get github.com/jteeuwen/go-bindata/...
-$ go get github.com/elazarl/go-bindata-assetfs/...
+go get github.com/jteeuwen/go-bindata/...
+go get github.com/elazarl/go-bindata-assetfs/...
```
-## Generating Assets.
+## Generating Assets
### Generate ui-assets.go
```sh
-$ yarn release
+yarn release
```
-This generates ui-assets.go in the current direcotry. Now do `make` in the parent directory to build the minio binary with the newly generated ui-assets.go
-### Run Minio Browser with live reload.
+This generates ui-assets.go in the current direcotry. Now do `make` in the parent directory to build the minio binary with the newly generated ``ui-assets.go``
+
+### Run Minio Browser with live reload
```sh
-$ yarn dev
+yarn dev
```
Open [http://localhost:8080/minio/](http://localhost:8080/minio/) in your browser to play with the application
+
+### Run Minio Browser with live reload on custom port
+
+Edit `browser/webpack.config.js`
+
+```diff
+diff --git a/browser/webpack.config.js b/browser/webpack.config.js
+index 3ccdaba..9496c56 100644
+--- a/browser/webpack.config.js
++++ b/browser/webpack.config.js
+@@ -58,6 +58,7 @@ var exports = {
+ historyApiFallback: {
+ index: '/minio/'
+ },
++ port: 8888,
+ proxy: {
+ '/minio/webrpc': {
+ target: 'http://localhost:9000',
+@@ -97,7 +98,7 @@ var exports = {
+ if (process.env.NODE_ENV === 'dev') {
+ exports.entry = [
+ 'webpack/hot/dev-server',
+- 'webpack-dev-server/client?http://localhost:8080',
++ 'webpack-dev-server/client?http://localhost:8888',
+ path.resolve(__dirname, 'app/index.js')
+ ]
+ }
+```
+
+```sh
+yarn dev
+```
+
+Open [http://localhost:8888/minio/](http://localhost:8888/minio/) in your browser to play with the application
diff --git a/browser/app/js/actions.js b/browser/app/js/actions.js
index 979f1ad97..c9b2f72bf 100644
--- a/browser/app/js/actions.js
+++ b/browser/app/js/actions.js
@@ -56,6 +56,7 @@ export const SET_POLICIES = 'SET_POLICIES'
export const SET_SHARE_OBJECT = 'SET_SHARE_OBJECT'
export const DELETE_CONFIRMATION = 'DELETE_CONFIRMATION'
export const SET_PREFIX_WRITABLE = 'SET_PREFIX_WRITABLE'
+export const REMOVE_OBJECT = 'REMOVE_OBJECT'
export const showDeleteConfirmation = (object) => {
return {
@@ -206,6 +207,13 @@ export const showAlert = alert => {
}
}
+export const removeObject = object => {
+ return {
+ type: REMOVE_OBJECT,
+ object
+ }
+}
+
export const setSidebarStatus = (status) => {
return {
type: SET_SIDEBAR_STATUS,
@@ -227,10 +235,12 @@ export const setVisibleBuckets = visibleBuckets => {
}
}
-export const setObjects = (objects) => {
+export const setObjects = (objects, marker, istruncated) => {
return {
type: SET_OBJECTS,
- objects
+ objects,
+ marker,
+ istruncated
}
}
@@ -284,22 +294,63 @@ export const selectBucket = (newCurrentBucket, prefix) => {
}
}
+export const listObjects = () => {
+ return (dispatch, getState) => {
+ const {currentBucket, currentPath, marker, objects, istruncated, web} = getState()
+ if (!istruncated) return
+ web.ListObjects({
+ bucketName: currentBucket,
+ prefix: currentPath,
+ marker: marker
+ })
+ .then(res => {
+ let objects = res.objects
+ if (!objects)
+ objects = []
+ objects = objects.map(object => {
+ object.name = object.name.replace(`${currentPath}`, '');
+ return object
+ })
+ dispatch(setObjects(objects, res.nextmarker, res.istruncated))
+ dispatch(setPrefixWritable(res.writable))
+ dispatch(setLoadBucket(''))
+ dispatch(setLoadPath(''))
+ })
+ .catch(err => {
+ dispatch(showAlert({
+ type: 'danger',
+ message: err.message
+ }))
+ dispatch(setLoadBucket(''))
+ dispatch(setLoadPath(''))
+ // Use browserHistory.replace instead of push so that browser back button works fine.
+ browserHistory.replace(`${minioBrowserPrefix}/login`)
+ })
+ }
+}
+
export const selectPrefix = prefix => {
return (dispatch, getState) => {
const {currentBucket, web} = getState()
+ dispatch(setObjects([], "", false))
dispatch(setLoadPath(prefix))
web.ListObjects({
bucketName: currentBucket,
- prefix
+ prefix,
+ marker: ""
})
.then(res => {
let objects = res.objects
if (!objects)
objects = []
+ objects = objects.map(object => {
+ object.name = object.name.replace(`${prefix}`, '');
+ return object
+ })
dispatch(setObjects(
- utils.sortObjectsByName(objects.map(object => {
- object.name = object.name.replace(`${prefix}`, ''); return object
- }))
+ objects,
+ res.nextmarker,
+ res.istruncated
))
dispatch(setPrefixWritable(res.writable))
dispatch(setSortNameOrder(false))
@@ -314,8 +365,8 @@ export const selectPrefix = prefix => {
}))
dispatch(setLoadBucket(''))
dispatch(setLoadPath(''))
- // Use browserHistory.replace instead of push so that browser back button works fine.
- browserHistory.replace(`${minioBrowserPrefix}/login`)
+ // Use browserHistory.replace instead of push so that browser back button works fine.
+ browserHistory.replace(`${minioBrowserPrefix}/login`)
})
}
}
diff --git a/browser/app/js/components/Browse.js b/browser/app/js/components/Browse.js
index 671552529..6458ad22b 100644
--- a/browser/app/js/components/Browse.js
+++ b/browser/app/js/components/Browse.js
@@ -47,6 +47,7 @@ import * as mime from '../mime'
import { minioBrowserPrefix } from '../constants'
import CopyToClipboard from 'react-copy-to-clipboard'
import storage from 'local-storage-fallback'
+import InfiniteScroll from 'react-infinite-scroller';
export default class Browse extends React.Component {
componentDidMount() {
@@ -110,9 +111,6 @@ export default class Browse extends React.Component {
if (!decPathname.endsWith('/'))
decPathname += '/'
if (decPathname === minioBrowserPrefix + '/') {
- dispatch(actions.setCurrentBucket(''))
- dispatch(actions.setCurrentPath(''))
- dispatch(actions.setObjects([]))
return
}
let obj = utils.pathSlice(decPathname)
@@ -140,6 +138,11 @@ export default class Browse extends React.Component {
this.props.dispatch(actions.setVisibleBuckets(buckets.filter(bucket => bucket.indexOf(e.target.value) > -1)))
}
+ listObjects() {
+ const {dispatch} = this.props
+ dispatch(actions.listObjects())
+ }
+
selectPrefix(e, prefix) {
e.preventDefault()
const {dispatch, currentPath, web, currentBucket} = this.props
@@ -231,7 +234,7 @@ export default class Browse extends React.Component {
})
.then(() => {
this.hideDeleteConfirmation()
- dispatch(actions.selectPrefix(currentPath))
+ dispatch(actions.removeObject(deleteConfirmation.object))
})
.catch(e => dispatch(actions.showAlert({
type: 'danger',
@@ -296,11 +299,6 @@ export default class Browse extends React.Component {
browserHistory.push(`${minioBrowserPrefix}/login`)
}
- landingPage(e) {
- e.preventDefault()
- this.props.dispatch(actions.selectBucket(this.props.buckets[0]))
- }
-
fullScreen(e) {
e.preventDefault()
let el = document.documentElement
@@ -365,7 +363,6 @@ export default class Browse extends React.Component {
}
}
-
render() {
const {total, free} = this.props.storageInfo
const {showMakeBucketModal, alert, sortNameOrder, sortSizeOrder, sortDateOrder, showAbout, showBucketPolicy} = this.props
@@ -375,7 +372,7 @@ export default class Browse extends React.Component {
const {policies, currentBucket, currentPath} = this.props
const {deleteConfirmation} = this.props
const {shareObject} = this.props
- const {web, prefixWritable} = this.props
+ const {web, prefixWritable, istruncated} = this.props
// Don't always show the SettingsModal. This is done here instead of in
// SettingsModal.js so as to allow for #componentWillMount to handle
@@ -414,10 +411,10 @@ export default class Browse extends React.Component {
let freePercent = free * 100 / total
if (web.LoggedIn()) {
- browserDropdownButton =