001/*
002 * Syncany, www.syncany.org
003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com>
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package org.syncany.cli;
019
020import static java.util.Arrays.asList;
021
022import java.util.List;
023
024import joptsimple.OptionParser;
025import joptsimple.OptionSet;
026import joptsimple.OptionSpec;
027
028import org.syncany.Client;
029import org.syncany.operations.OperationResult;
030import org.syncany.operations.daemon.messages.ConnectToHostExternalEvent;
031import org.syncany.operations.update.AppInfo;
032import org.syncany.operations.update.UpdateOperation;
033import org.syncany.operations.update.UpdateOperationAction;
034import org.syncany.operations.update.UpdateOperationOptions;
035import org.syncany.operations.update.UpdateOperationResult;
036import org.syncany.operations.update.UpdateOperationResult.UpdateResultCode;
037
038import com.google.common.eventbus.Subscribe;
039
040public class UpdateCommand extends Command {
041        @Override
042        public CommandScope getRequiredCommandScope() {
043                return CommandScope.ANY;
044        }
045
046        @Override
047        public boolean canExecuteInDaemonScope() {
048                return false;
049        }
050
051        @Override
052        public int execute(String[] operationArgs) throws Exception {
053                UpdateOperationOptions operationOptions = parseOptions(operationArgs);
054                UpdateOperationResult operationResult = new UpdateOperation(config, operationOptions).execute();
055
056                printResults(operationResult);
057
058                return 0;
059        }
060
061        @Override
062        public UpdateOperationOptions parseOptions(String[] operationArgs) throws Exception {
063                UpdateOperationOptions operationOptions = new UpdateOperationOptions();
064
065                OptionParser parser = new OptionParser();
066                OptionSpec<Void> optionSnapshots = parser.acceptsAll(asList("s", "snapshot", "snapshots"));
067                OptionSpec<String> optionApiEndpoint = parser.acceptsAll(asList("a", "api-endpoint")).withRequiredArg();
068
069                OptionSet options = parser.parse(operationArgs);
070
071                // Action
072                List<?> nonOptionArgs = options.nonOptionArguments();
073
074                if (nonOptionArgs.size() == 0) {
075                        throw new Exception("Invalid syntax, please specify an action (check).");
076                }
077
078                // <action>
079                String actionStr = nonOptionArgs.get(0).toString();
080                UpdateOperationAction action = parseAction(actionStr);
081
082                operationOptions.setAction(action);
083
084                // --snapshots
085                operationOptions.setSnapshots(options.has(optionSnapshots));
086                
087                // --api-endpoint
088                if (options.has(optionApiEndpoint)) {
089                        operationOptions.setApiEndpoint(options.valueOf(optionApiEndpoint));
090                }
091
092                return operationOptions;
093        }
094
095        private UpdateOperationAction parseAction(String actionStr) throws Exception {
096                try {
097                        return UpdateOperationAction.valueOf(actionStr.toUpperCase());
098                }
099                catch (Exception e) {
100                        throw new Exception("Invalid syntax, unknown action '" + actionStr + "'");
101                }
102        }
103
104        @Override
105        public void printResults(OperationResult operationResult) {
106                UpdateOperationResult concreteOperationResult = (UpdateOperationResult) operationResult;
107
108                switch (concreteOperationResult.getAction()) {
109                        case CHECK:
110                                printResultCheck(concreteOperationResult);
111                                return;
112
113                        default:
114                                out.println("Unknown action: " + concreteOperationResult.getAction());
115                }
116        }
117
118        private void printResultCheck(UpdateOperationResult operationResult) {
119                if (operationResult.getResultCode() == UpdateResultCode.OK) {
120                        AppInfo remoteAppInfo = operationResult.getAppInfo();
121
122                        String localAppVersion = Client.getApplicationVersionFull();
123                        String remoteAppVersion = remoteAppInfo.getAppVersion();
124                        
125                        if (operationResult.isNewVersionAvailable()) {
126                                out.println("A new version is available. Local version is " + localAppVersion + ", remote version is " + remoteAppVersion);
127                                out.println("Download at " + remoteAppInfo.getDownloadUrl());
128                        }
129                        else {
130                                out.println("Up to date, at version " + localAppVersion);       
131                        }                       
132                }
133                else {
134                        out.println("Checking for updates failed. No connection? Try -d to get more details.");
135                        out.println();
136                }
137        }
138
139        @Subscribe
140        public void onConnectToHostEventReceived(ConnectToHostExternalEvent event) {
141                out.printr("Connecting to " + event.getHost() + " ...");
142        }
143}